Skip to content

Commit

Permalink
add arbitrary value support & tests (#10)
Browse files Browse the repository at this point in the history
* feat: add arbitrary value support

* test: add tests

* merge

* Match typography plugin test setup

* Use matchUtilities

* Simplify

Co-authored-by: Jordan Pittman <[email protected]>
  • Loading branch information
dgknca and thecrypticace authored Mar 1, 2022
1 parent d2320ea commit 23fa9b1
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 11 deletions.
146 changes: 146 additions & 0 deletions jest/customMatchers.js
Original file line number Diff line number Diff line change
@@ -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 }
},
})
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,20 @@
"singleQuote": true,
"trailingComma": "es5"
},
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest": "^27.4.4",
"postcss": "^8.2.2",
"prettier": "^2.5.1"
},
"peerDependencies": {
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
},
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/jest/customMatchers.js"
]
}
}
28 changes: 17 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
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 ({ matchUtilities, addUtilities, theme, variants, e }) {
const values = theme('lineClamp')

matchUtilities(
{
'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',
'-webkit-line-clamp': `${value}`,
},
}
}),
{
'.line-clamp-none': {
'-webkit-line-clamp': 'unset',
Expand Down
61 changes: 61 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const path = require('path')
const postcss = require('postcss')
const tailwindcss = require('tailwindcss')
const lineClampPlugin = require('.')

function run(config, plugin = tailwindcss) {
let { currentTestName } = expect.getState()
config = {
...{ plugins: [lineClampPlugin], corePlugins: { preflight: false } },
...config,
}

return postcss(plugin(config)).process('@tailwind utilities', {
from: `${path.resolve(__filename)}?test=${currentTestName}`,
})
}

it('should add the `line-clamp-{n}` components', () => {
const config = {
content: [{ raw: String.raw`<div class="line-clamp-2 line-clamp-[33] line-clamp-[var(--line-clamp-variable)]"></div>` }],
}

return run(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 = {
content: [{ raw: String.raw`<div class="line-clamp-none"></div>` }],
}

return run(config).then((result) => {
expect(result.css).toMatchCss(String.raw`
.line-clamp-none {
-webkit-line-clamp: unset;
}
`)
})
})

0 comments on commit 23fa9b1

Please sign in to comment.