From c1a7095c906b845c068782516960e00373cab2df Mon Sep 17 00:00:00 2001 From: dgknca Date: Sun, 12 Dec 2021 13:22:07 +0300 Subject: [PATCH 1/6] feat: add arbitrary value support --- package.json | 2 +- src/index.js | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fbe4435..21db4de 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,6 @@ "autoprefixer": "^10.2.0", "clean-css": "^4.2.1", "postcss": "^8.2.2", - "tailwindcss": "^2.0.2" + "tailwindcss": "^3.0.1" } } diff --git a/src/index.js b/src/index.js index f354e23..bb957a6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,17 +1,33 @@ const plugin = require('tailwindcss/plugin') +const baseStyles = { + overflow: 'hidden', + display: '-webkit-box', + '-webkit-box-orient': 'vertical', +} + const lineClamp = plugin( - function ({ addUtilities, theme, variants, e }) { + function ({ matchComponents, addUtilities, theme, variants, e }) { const values = theme('lineClamp') + matchComponents( + { + 'line-clamp': (value) => [ + { + ...baseStyles, + '-webkit-line-clamp': `${value}`, + } + ] + }, + { values } + ) + addUtilities( [ Object.entries(values).map(([key, value]) => { return { [`.${e(`line-clamp-${key}`)}`]: { - overflow: 'hidden', - display: '-webkit-box', - '-webkit-box-orient': 'vertical', + ...baseStyles, '-webkit-line-clamp': `${value}`, }, } From 98f3848295c1333334a6a48ab8bfd62de4fe1142 Mon Sep 17 00:00:00 2001 From: dgknca Date: Sun, 12 Dec 2021 13:23:07 +0300 Subject: [PATCH 2/6] test: add tests --- package.json | 3 ++ test/index.test.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 test/index.test.js diff --git a/package.json b/package.json index 21db4de..b4aa920 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "trailingComma": "es5" }, "scripts": { + "test": "jest", "prepublishOnly": "node scripts/build.js" }, "peerDependencies": { @@ -22,6 +23,8 @@ "devDependencies": { "autoprefixer": "^10.2.0", "clean-css": "^4.2.1", + "jest": "^27.4.4", + "jest-matcher-css": "^1.1.0", "postcss": "^8.2.2", "tailwindcss": "^3.0.1" } diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..51c499a --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,68 @@ +const cssMatcher = require('jest-matcher-css') +const postcss = require('postcss') +const tailwindcss = require('tailwindcss') + +const defaultOptions = { + corePlugins: { preflight: false }, + plugins: [require('../src')], +} + +function run(input, config, plugin = tailwindcss) { + return postcss( + plugin(config) + ) + .process(input, { + from: undefined + }) +} + +expect.extend({ + toMatchCss: cssMatcher +}) + +it('should add the `line-clamp-{n}` components', () => { + const config = { + ...defaultOptions, + content: [{ raw: String.raw`
` }], + } + + return run('@tailwind components;', config).then((result) => { + expect(result.css).toMatchCss(String.raw` + .line-clamp-2 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + } + + .line-clamp-\[33\] { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 33; + } + + .line-clamp-\[var\(--line-clamp-variable\)\] { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: var(--line-clamp-variable); + } + `) + }) +}) + +it('should add the `line-clamp-none` utility', () => { + const config = { + ...defaultOptions, + content: [{ raw: String.raw`
` }], + } + + return run('@tailwind utilities;', config).then((result) => { + expect(result.css).toMatchCss(String.raw` + .line-clamp-none { + -webkit-line-clamp: unset; + } + `) + }) +}) \ No newline at end of file From 5198fd6cc65125230987f7a79e7dd217cbeef613 Mon Sep 17 00:00:00 2001 From: dgknca Date: Wed, 15 Dec 2021 22:39:20 +0300 Subject: [PATCH 3/6] merge --- CHANGELOG.md | 4 +++- dist/.gitignore | 3 --- dist/.npmignore | 0 package.json | 5 +---- scripts/build.js | 36 ------------------------------------ 5 files changed, 4 insertions(+), 44 deletions(-) delete mode 100644 dist/.gitignore delete mode 100644 dist/.npmignore delete mode 100644 scripts/build.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f97d942..334dcad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Added + +- Remove `dist` folder and related dependencies ([#11](https://github.com/tailwindlabs/tailwindcss-line-clamp/pull/11)) ## [0.3.0] - 2021-12-09 diff --git a/dist/.gitignore b/dist/.gitignore deleted file mode 100644 index 2f41fac..0000000 --- a/dist/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!.npmignore diff --git a/dist/.npmignore b/dist/.npmignore deleted file mode 100644 index e69de29..0000000 diff --git a/package.json b/package.json index b4aa920..6d86a2f 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,8 @@ "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" }, "devDependencies": { - "autoprefixer": "^10.2.0", - "clean-css": "^4.2.1", "jest": "^27.4.4", "jest-matcher-css": "^1.1.0", - "postcss": "^8.2.2", - "tailwindcss": "^3.0.1" + "postcss": "^8.2.2" } } diff --git a/scripts/build.js b/scripts/build.js deleted file mode 100644 index 9f110c3..0000000 --- a/scripts/build.js +++ /dev/null @@ -1,36 +0,0 @@ -const fs = require('fs') -const postcss = require('postcss') -const tailwind = require('tailwindcss') -const CleanCSS = require('clean-css') - -function buildDistFile(filename) { - return postcss([ - tailwind({ - corePlugins: false, - plugins: [require('../src/index.js')], - }), - require('autoprefixer'), - ]) - .process('@tailwind utilities', { - from: null, - to: `./dist/${filename}.css`, - map: false, - }) - .then((result) => { - fs.writeFileSync(`./dist/${filename}.css`, result.css) - return result - }) - .then((result) => { - const minified = new CleanCSS().minify(result.css) - fs.writeFileSync(`./dist/${filename}.min.css`, minified.styles) - }) - .catch((error) => { - console.log(error) - }) -} - -console.info('Building CSS...') - -Promise.all([buildDistFile('line-clamp')]).then(() => { - console.log('Finished building CSS.') -}) From 78ab2e982c37b49936b06d59c4117b8dc966acff Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 1 Mar 2022 10:53:53 -0500 Subject: [PATCH 4/6] Match typography plugin test setup --- jest/customMatchers.js | 146 +++++++++++++++++++++++++++++++++++++++++ package.json | 9 ++- test/index.test.js | 31 ++++----- 3 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 jest/customMatchers.js diff --git a/jest/customMatchers.js b/jest/customMatchers.js new file mode 100644 index 0000000..c60acee --- /dev/null +++ b/jest/customMatchers.js @@ -0,0 +1,146 @@ +const prettier = require('prettier') +const { diff } = require('jest-diff') + +function format(input) { + return prettier.format(input, { + parser: 'css', + printWidth: 100, + }) +} + +expect.extend({ + // Compare two CSS strings with all whitespace removed + // This is probably naive but it's fast and works well enough. + toMatchCss(received, argument) { + function stripped(str) { + return str.replace(/\s/g, '').replace(/;/g, '') + } + + const options = { + comment: 'stripped(received) === stripped(argument)', + isNot: this.isNot, + promise: this.promise, + } + + const pass = stripped(received) === stripped(argument) + + const message = pass + ? () => { + return ( + this.utils.matcherHint('toMatchCss', undefined, undefined, options) + + '\n\n' + + `Expected: not ${this.utils.printExpected(format(received))}\n` + + `Received: ${this.utils.printReceived(format(argument))}` + ) + } + : () => { + const actual = format(received) + const expected = format(argument) + + const diffString = diff(expected, actual, { + expand: this.expand, + }) + + return ( + this.utils.matcherHint('toMatchCss', undefined, undefined, options) + + '\n\n' + + (diffString && diffString.includes('- Expect') + ? `Difference:\n\n${diffString}` + : `Expected: ${this.utils.printExpected(expected)}\n` + + `Received: ${this.utils.printReceived(actual)}`) + ) + } + + return { actual: received, message, pass } + }, + toIncludeCss(received, argument) { + const options = { + comment: 'stripped(received).includes(stripped(argument))', + isNot: this.isNot, + promise: this.promise, + } + + const actual = format(received) + const expected = format(argument) + + const pass = actual.includes(expected) + + const message = pass + ? () => { + return ( + this.utils.matcherHint('toIncludeCss', undefined, undefined, options) + + '\n\n' + + `Expected: not ${this.utils.printExpected(format(received))}\n` + + `Received: ${this.utils.printReceived(format(argument))}` + ) + } + : () => { + const diffString = diff(expected, actual, { + expand: this.expand, + }) + + return ( + this.utils.matcherHint('toIncludeCss', undefined, undefined, options) + + '\n\n' + + (diffString && diffString.includes('- Expect') + ? `Difference:\n\n${diffString}` + : `Expected: ${this.utils.printExpected(expected)}\n` + + `Received: ${this.utils.printReceived(actual)}`) + ) + } + + return { actual: received, message, pass } + }, +}) + +expect.extend({ + // Compare two CSS strings with all whitespace removed + // This is probably naive but it's fast and works well enough. + toMatchFormattedCss(received, argument) { + function format(input) { + return prettier.format(input.replace(/\n/g, ''), { + parser: 'css', + printWidth: 100, + }) + } + const options = { + comment: 'stripped(received) === stripped(argument)', + isNot: this.isNot, + promise: this.promise, + } + + let formattedReceived = format(received) + let formattedArgument = format(argument) + + const pass = formattedReceived === formattedArgument + + const message = pass + ? () => { + return ( + this.utils.matcherHint('toMatchCss', undefined, undefined, options) + + '\n\n' + + `Expected: not ${this.utils.printExpected(formattedReceived)}\n` + + `Received: ${this.utils.printReceived(formattedArgument)}` + ) + } + : () => { + const actual = formattedReceived + const expected = formattedArgument + + const diffString = diff(expected, actual, { + expand: this.expand, + }) + + return ( + this.utils.matcherHint('toMatchCss', undefined, undefined, options) + + '\n\n' + + (diffString && diffString.includes('- Expect') + ? `Difference:\n\n${diffString}` + : `Expected: ${this.utils.printExpected(expected)}\n` + + `Received: ${this.utils.printReceived(actual)}`) + ) + } + + return { actual: received, message, pass } + }, +}) \ No newline at end of file diff --git a/package.json b/package.json index a19d294..f1f1735 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,15 @@ }, "devDependencies": { "jest": "^27.4.4", - "jest-matcher-css": "^1.1.0", - "postcss": "^8.2.2" + "postcss": "^8.2.2", + "prettier": "^2.5.1" }, "peerDependencies": { "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + }, + "jest": { + "setupFilesAfterEnv": [ + "/jest/customMatchers.js" + ] } } diff --git a/test/index.test.js b/test/index.test.js index 51c499a..56f8f37 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,32 +1,26 @@ -const cssMatcher = require('jest-matcher-css') +const path = require('path') const postcss = require('postcss') const tailwindcss = require('tailwindcss') +const lineClampPlugin = require('../src') -const defaultOptions = { - corePlugins: { preflight: false }, - plugins: [require('../src')], -} +function run(config, plugin = tailwindcss) { + let { currentTestName } = expect.getState() + config = { + ...{ plugins: [lineClampPlugin], corePlugins: { preflight: false } }, + ...config, + } -function run(input, config, plugin = tailwindcss) { - return postcss( - plugin(config) - ) - .process(input, { - from: undefined + return postcss(plugin(config)).process('@tailwind utilities', { + from: `${path.resolve(__filename)}?test=${currentTestName}`, }) } -expect.extend({ - toMatchCss: cssMatcher -}) - it('should add the `line-clamp-{n}` components', () => { const config = { - ...defaultOptions, content: [{ raw: String.raw`
` }], } - return run('@tailwind components;', config).then((result) => { + return run(config).then((result) => { expect(result.css).toMatchCss(String.raw` .line-clamp-2 { overflow: hidden; @@ -54,11 +48,10 @@ it('should add the `line-clamp-{n}` components', () => { it('should add the `line-clamp-none` utility', () => { const config = { - ...defaultOptions, content: [{ raw: String.raw`
` }], } - return run('@tailwind utilities;', config).then((result) => { + return run(config).then((result) => { expect(result.css).toMatchCss(String.raw` .line-clamp-none { -webkit-line-clamp: unset; From 1fc9f0a632baae00969a8ee16501cdd1b8669836 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 1 Mar 2022 10:57:00 -0500 Subject: [PATCH 5/6] Use matchUtilities --- src/index.js | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/index.js b/src/index.js index bb957a6..2be8a97 100644 --- a/src/index.js +++ b/src/index.js @@ -7,21 +7,38 @@ const baseStyles = { } const lineClamp = plugin( - function ({ matchComponents, addUtilities, theme, variants, e }) { + function ({ matchUtilities, addUtilities, theme, variants, e }) { const values = theme('lineClamp') - matchComponents( - { - 'line-clamp': (value) => [ + if (matchUtilities) { + // Tailwind CSS v3.0+ + matchUtilities( + { + 'line-clamp': (value) => [ + { + ...baseStyles, + '-webkit-line-clamp': `${value}`, + } + ] + }, + { values } + ) + + addUtilities( + [ { - ...baseStyles, - '-webkit-line-clamp': `${value}`, - } - ] - }, - { values } - ) + '.line-clamp-none': { + '-webkit-line-clamp': 'unset', + }, + }, + ], + variants('lineClamp') + ) + + return + } + // Tailwind CSS v2.0+ addUtilities( [ Object.entries(values).map(([key, value]) => { From 91567372d88b34816f0b6087062d01bda6be6b29 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 1 Mar 2022 11:14:10 -0500 Subject: [PATCH 6/6] Simplify --- src/index.js | 45 ++++++++----------------------------- {test => src}/index.test.js | 2 +- 2 files changed, 10 insertions(+), 37 deletions(-) rename {test => src}/index.test.js (97%) diff --git a/src/index.js b/src/index.js index 2be8a97..2d5a978 100644 --- a/src/index.js +++ b/src/index.js @@ -10,45 +10,18 @@ const lineClamp = plugin( function ({ matchUtilities, addUtilities, theme, variants, e }) { const values = theme('lineClamp') - if (matchUtilities) { - // Tailwind CSS v3.0+ - matchUtilities( - { - 'line-clamp': (value) => [ - { - ...baseStyles, - '-webkit-line-clamp': `${value}`, - } - ] - }, - { values } - ) - - addUtilities( - [ - { - '.line-clamp-none': { - '-webkit-line-clamp': 'unset', - }, - }, - ], - variants('lineClamp') - ) - - return - } + matchUtilities( + { + 'line-clamp': (value) => ({ + ...baseStyles, + '-webkit-line-clamp': `${value}`, + }) + }, + { values } + ) - // Tailwind CSS v2.0+ addUtilities( [ - Object.entries(values).map(([key, value]) => { - return { - [`.${e(`line-clamp-${key}`)}`]: { - ...baseStyles, - '-webkit-line-clamp': `${value}`, - }, - } - }), { '.line-clamp-none': { '-webkit-line-clamp': 'unset', diff --git a/test/index.test.js b/src/index.test.js similarity index 97% rename from test/index.test.js rename to src/index.test.js index 56f8f37..92de2f6 100644 --- a/test/index.test.js +++ b/src/index.test.js @@ -1,7 +1,7 @@ const path = require('path') const postcss = require('postcss') const tailwindcss = require('tailwindcss') -const lineClampPlugin = require('../src') +const lineClampPlugin = require('.') function run(config, plugin = tailwindcss) { let { currentTestName } = expect.getState()