mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Integrations setup (#4354)
* add integration test tools * setup jest in the integrations folder * add `test:integrations` script The default `npm test` script will ignore all the tests in the `integrations` folder. * add integration tests with `webpack 5` * add integration tests with `postcss-cli` * add `npm run install:integrations` script This script will run `npm install` in every integration, and in the integrations folder itself (to setup Jest for example). * add `toIncludeCss` custom matcher * increate Jest timeout for integration tests * add integration tests with `vite` * add integration tests with `webpack 4` * add isomorphic fetch * add the ability to wait for specific stdout/stderr output * write vite tests, assert using API calls We will wait for the correct stdout/stderr output, once we know that we can request the fresh css, we will fetch it and make assertions accordingly. Port is currently hardcoded, maybe we should use a packaage to ensure that we use a free port. * add integration tests with `rollup` * add integration tests with `parcel` * run all integration tests in band * add .gitignore in integrations folder
This commit is contained in:
parent
7d4f053bb6
commit
7565099c1f
1
integrations/.gitignore
vendored
Normal file
1
integrations/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
99
integrations/execute.js
Normal file
99
integrations/execute.js
Normal file
@ -0,0 +1,99 @@
|
||||
let path = require('path')
|
||||
let { spawn } = require('child_process')
|
||||
let resolveToolRoot = require('./resolve-tool-root')
|
||||
|
||||
let runningProcessess = []
|
||||
|
||||
afterEach(() => {
|
||||
runningProcessess.splice(0).forEach((runningProcess) => runningProcess.stop())
|
||||
})
|
||||
|
||||
module.exports = function $(command, options = {}) {
|
||||
let abortController = new AbortController()
|
||||
let cwd = resolveToolRoot()
|
||||
|
||||
let args = command.split(' ')
|
||||
command = args.shift()
|
||||
command = path.resolve(cwd, 'node_modules', '.bin', command)
|
||||
|
||||
let stdoutMessages = []
|
||||
let stderrMessages = []
|
||||
|
||||
let stdoutActors = []
|
||||
let stderrActors = []
|
||||
|
||||
function notifyNext(actors, messages) {
|
||||
if (actors.length <= 0) return
|
||||
let [next] = actors
|
||||
|
||||
for (let [idx, message] of messages.entries()) {
|
||||
if (next.predicate(message)) {
|
||||
messages.splice(0, idx + 1)
|
||||
let actorIdx = actors.indexOf(next)
|
||||
actors.splice(actorIdx, 1)
|
||||
next.resolve()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function notifyNextStdoutActor() {
|
||||
return notifyNext(stdoutActors, stdoutMessages)
|
||||
}
|
||||
|
||||
function notifyNextStderrActor() {
|
||||
return notifyNext(stderrActors, stderrMessages)
|
||||
}
|
||||
|
||||
let runningProcess = new Promise((resolve, reject) => {
|
||||
let child = spawn(command, args, {
|
||||
...options,
|
||||
env: {
|
||||
...process.env,
|
||||
...options.env,
|
||||
},
|
||||
signal: abortController.signal,
|
||||
cwd,
|
||||
})
|
||||
|
||||
let stdout = ''
|
||||
let stderr = ''
|
||||
|
||||
child.stdout.on('data', (data) => {
|
||||
stdoutMessages.push(data.toString())
|
||||
notifyNextStdoutActor()
|
||||
stdout += data
|
||||
})
|
||||
|
||||
child.stderr.on('data', (data) => {
|
||||
stderrMessages.push(data.toString())
|
||||
notifyNextStderrActor()
|
||||
stderr += data
|
||||
})
|
||||
|
||||
child.on('close', (code, signal) => {
|
||||
;(signal === 'SIGTERM' ? resolve : code === 0 ? resolve : reject)({ code, stdout, stderr })
|
||||
})
|
||||
})
|
||||
|
||||
runningProcessess.push(runningProcess)
|
||||
|
||||
return Object.assign(runningProcess, {
|
||||
stop() {
|
||||
abortController.abort()
|
||||
return runningProcess
|
||||
},
|
||||
onStdout(predicate) {
|
||||
return new Promise((resolve) => {
|
||||
stdoutActors.push({ predicate, resolve })
|
||||
notifyNextStdoutActor()
|
||||
})
|
||||
},
|
||||
onStderr(predicate) {
|
||||
return new Promise((resolve) => {
|
||||
stderrActors.push({ predicate, resolve })
|
||||
notifyNextStderrActor()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
4
integrations/html.js
Normal file
4
integrations/html.js
Normal file
@ -0,0 +1,4 @@
|
||||
// Small helper to allow for html highlighting / formatting in most editors.
|
||||
module.exports = function html(templates) {
|
||||
return templates.join('')
|
||||
}
|
||||
139
integrations/io.js
Normal file
139
integrations/io.js
Normal file
@ -0,0 +1,139 @@
|
||||
let { rm, existsSync } = require('fs')
|
||||
let path = require('path')
|
||||
let fs = require('fs/promises')
|
||||
|
||||
let chokidar = require('chokidar')
|
||||
|
||||
let resolveToolRoot = require('./resolve-tool-root')
|
||||
|
||||
module.exports = function ({
|
||||
/** Output directory, relative to the tool. */
|
||||
output = 'dist',
|
||||
|
||||
/** Input directory, relative to the tool. */
|
||||
input = 'src',
|
||||
|
||||
/** Whether or not you want to cleanup the output directory. */
|
||||
cleanup = true,
|
||||
} = {}) {
|
||||
let toolRoot = resolveToolRoot()
|
||||
let fileCache = {}
|
||||
|
||||
let absoluteOutputFolder = path.resolve(toolRoot, output)
|
||||
let absoluteInputFolder = path.resolve(toolRoot, input)
|
||||
|
||||
if (cleanup) {
|
||||
beforeAll((done) => rm(absoluteOutputFolder, { recursive: true, force: true }, done))
|
||||
afterEach((done) => rm(absoluteOutputFolder, { recursive: true, force: true }, done))
|
||||
}
|
||||
|
||||
// Restore all written files
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
Object.entries(fileCache).map(([file, content]) => fs.writeFile(file, content, 'utf8'))
|
||||
)
|
||||
})
|
||||
|
||||
async function readdir(start, parent = []) {
|
||||
let files = await fs.readdir(start, { withFileTypes: true })
|
||||
let resolvedFiles = await Promise.all(
|
||||
files.map((file) => {
|
||||
if (file.isDirectory()) {
|
||||
return readdir(path.resolve(start, file.name), [...parent, file.name])
|
||||
}
|
||||
return parent.concat(file.name).join(path.sep)
|
||||
})
|
||||
)
|
||||
return resolvedFiles.flat(Infinity)
|
||||
}
|
||||
|
||||
async function resolveFile(fileOrRegex, directory) {
|
||||
if (fileOrRegex instanceof RegExp) {
|
||||
let files = await readdir(directory)
|
||||
if (files.length === 0) {
|
||||
throw new Error(`No files exists in "${directory}"`)
|
||||
}
|
||||
|
||||
let filtered = files.filter((file) => fileOrRegex.test(file))
|
||||
if (filtered.length === 0) {
|
||||
throw new Error(`Not a single file matched: ${fileOrRegex}`)
|
||||
} else if (filtered.length > 1) {
|
||||
throw new Error(`Multiple files matched: ${fileOrRegex}`)
|
||||
}
|
||||
|
||||
return filtered[0]
|
||||
}
|
||||
|
||||
return fileOrRegex
|
||||
}
|
||||
|
||||
return {
|
||||
async readOutputFile(file) {
|
||||
file = await resolveFile(file, absoluteOutputFolder)
|
||||
return fs.readFile(path.resolve(absoluteOutputFolder, file), 'utf8')
|
||||
},
|
||||
async appendToInputFile(file, contents) {
|
||||
let filePath = path.resolve(absoluteInputFolder, file)
|
||||
if (!fileCache[filePath]) {
|
||||
fileCache[filePath] = await fs.readFile(filePath, 'utf8')
|
||||
}
|
||||
|
||||
return fs.appendFile(filePath, contents, 'utf8')
|
||||
},
|
||||
async writeInputFile(file, contents) {
|
||||
let filePath = path.resolve(absoluteInputFolder, file)
|
||||
if (!fileCache[filePath]) {
|
||||
fileCache[filePath] = await fs.readFile(filePath, 'utf8')
|
||||
}
|
||||
|
||||
return fs.writeFile(path.resolve(absoluteInputFolder, file), contents, 'utf8')
|
||||
},
|
||||
async waitForOutputFileCreation(file) {
|
||||
if (file instanceof RegExp) {
|
||||
let r = file
|
||||
let watcher = chokidar.watch(absoluteOutputFolder)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
watcher.on('add', (file) => {
|
||||
if (r.test(file)) {
|
||||
watcher.close()
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
let filePath = path.resolve(absoluteOutputFolder, file)
|
||||
let watcher = chokidar.watch(filePath)
|
||||
|
||||
let watcherPromise = new Promise((resolve) => {
|
||||
watcher.once('add', () => {
|
||||
watcher.close()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
if (existsSync(filePath)) {
|
||||
watcher.close()
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return watcherPromise
|
||||
}
|
||||
},
|
||||
async waitForOutputFileChange(file, cb = () => {}) {
|
||||
file = await resolveFile(file, absoluteOutputFolder)
|
||||
|
||||
let filePath = path.resolve(absoluteOutputFolder, file)
|
||||
let watcher = chokidar.watch(filePath)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let chain = Promise.resolve()
|
||||
watcher.once('change', () => {
|
||||
watcher.close()
|
||||
chain.then(() => resolve())
|
||||
})
|
||||
chain.then(() => cb())
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
11125
integrations/package-lock.json
generated
Normal file
11125
integrations/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
integrations/package.json
Normal file
18
integrations/package.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "integrations",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"test": "jest --runInBand"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 30000,
|
||||
"projects": [
|
||||
"<rootDir>/*/package.json"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"jest": "^26.6.3"
|
||||
}
|
||||
}
|
||||
5
integrations/parcel/.gitignore
vendored
Normal file
5
integrations/parcel/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
dist/
|
||||
node_modules/
|
||||
.parcel-cache/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
25858
integrations/parcel/package-lock.json
generated
Normal file
25858
integrations/parcel/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
integrations/parcel/package.json
Normal file
19
integrations/parcel/package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "parcel",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "parcel build ./src/index.html --no-cache",
|
||||
"dev": "parcel watch ./src/index.html --no-cache",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "parcel",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"parcel": "nightly"
|
||||
}
|
||||
}
|
||||
5
integrations/parcel/postcss.config.js
Normal file
5
integrations/parcel/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
3
integrations/parcel/src/index.css
Normal file
3
integrations/parcel/src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
12
integrations/parcel/src/index.html
Normal file
12
integrations/parcel/src/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="./index.css">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
15
integrations/parcel/tailwind.config.js
Normal file
15
integrations/parcel/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
262
integrations/parcel/tests/integration.test.js
Normal file
262
integrations/parcel/tests/integration.test.js
Normal file
@ -0,0 +1,262 @@
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold"></div>
|
||||
`
|
||||
)
|
||||
|
||||
await $('parcel build ./src/index.html --no-cache', {
|
||||
env: { NODE_ENV: 'production' },
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $('parcel watch ./src/index.html --no-cache', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation(/index\.\w+\.css$/)
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange(/index\.\w+\.css$/, async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange(/index\.\w+\.css$/, async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold md:font-medium"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $('parcel watch ./src/index.html --no-cache', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation(/index\.\w+\.css$/)
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange(/index\.\w+\.css$/, async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold btn"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $('parcel watch ./src/index.html --no-cache', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation(/index\.\w+\.css$/)
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange(/index\.\w+\.css$/, async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange(/index\.\w+\.css$/, async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index\.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
4
integrations/postcss-cli/.gitignore
vendored
Normal file
4
integrations/postcss-cli/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
1914
integrations/postcss-cli/package-lock.json
generated
Normal file
1914
integrations/postcss-cli/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
integrations/postcss-cli/package.json
Normal file
19
integrations/postcss-cli/package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "postcss-cli",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production postcss ./src/index.css -o ./dist/main.css",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "PostCSS CLI",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"postcss": "^8.2.15",
|
||||
"postcss-cli": "^8.3.1"
|
||||
}
|
||||
}
|
||||
5
integrations/postcss-cli/postcss.config.js
Normal file
5
integrations/postcss-cli/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
3
integrations/postcss-cli/src/index.css
Normal file
3
integrations/postcss-cli/src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
11
integrations/postcss-cli/src/index.html
Normal file
11
integrations/postcss-cli/src/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
15
integrations/postcss-cli/tailwind.config.js
Normal file
15
integrations/postcss-cli/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
238
integrations/postcss-cli/tests/integration.test.js
Normal file
238
integrations/postcss-cli/tests/integration.test.js
Normal file
@ -0,0 +1,238 @@
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
await $('postcss ./src/index.css -o ./dist/main.css', {
|
||||
env: { NODE_ENV: 'production' },
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
14
integrations/resolve-tool-root.js
Normal file
14
integrations/resolve-tool-root.js
Normal file
@ -0,0 +1,14 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = function resolveToolRoot() {
|
||||
let { testPath } = expect.getState()
|
||||
let separator = '/' // TODO: Does this resolve correctly on windows, or should we use `path.sep` instead.
|
||||
|
||||
return path.resolve(
|
||||
__dirname,
|
||||
testPath
|
||||
.replace(__dirname + separator, '')
|
||||
.split(separator)
|
||||
.shift()
|
||||
)
|
||||
}
|
||||
4
integrations/rollup/.gitignore
vendored
Normal file
4
integrations/rollup/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
9940
integrations/rollup/package-lock.json
generated
Normal file
9940
integrations/rollup/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
integrations/rollup/package.json
Normal file
19
integrations/rollup/package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "rollup.js",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "rollup.js",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"rollup": "^2.48.0",
|
||||
"rollup-plugin-postcss": "^4.0.0"
|
||||
}
|
||||
}
|
||||
5
integrations/rollup/postcss.config.js
Normal file
5
integrations/rollup/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
14
integrations/rollup/rollup.config.js
Normal file
14
integrations/rollup/rollup.config.js
Normal file
@ -0,0 +1,14 @@
|
||||
import postcss from 'rollup-plugin-postcss'
|
||||
|
||||
export default {
|
||||
input: './src/index.js',
|
||||
output: {
|
||||
file: './dist/index.js',
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [
|
||||
postcss({
|
||||
extract: true,
|
||||
}),
|
||||
],
|
||||
}
|
||||
3
integrations/rollup/src/index.css
Normal file
3
integrations/rollup/src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
11
integrations/rollup/src/index.html
Normal file
11
integrations/rollup/src/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
integrations/rollup/src/index.js
Normal file
1
integrations/rollup/src/index.js
Normal file
@ -0,0 +1 @@
|
||||
import './index.css'
|
||||
15
integrations/rollup/tailwind.config.js
Normal file
15
integrations/rollup/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
238
integrations/rollup/tests/integration.test.js
Normal file
238
integrations/rollup/tests/integration.test.js
Normal file
@ -0,0 +1,238 @@
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
await $('rollup -c', {
|
||||
env: { NODE_ENV: 'production' },
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
6
integrations/syntax.js
Normal file
6
integrations/syntax.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Small helper to allow for css, html and JavaScript highlighting / formatting in most editors.
|
||||
function syntax(templates) {
|
||||
return templates.join('')
|
||||
}
|
||||
|
||||
module.exports = { css: syntax, html: syntax, javascript: syntax }
|
||||
4
integrations/vite/.gitignore
vendored
Normal file
4
integrations/vite/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
3
integrations/vite/index.css
Normal file
3
integrations/vite/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
12
integrations/vite/index.html
Normal file
12
integrations/vite/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="./index.css">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
1
integrations/vite/index.js
Normal file
1
integrations/vite/index.js
Normal file
@ -0,0 +1 @@
|
||||
import './index.css'
|
||||
274
integrations/vite/package-lock.json
generated
Normal file
274
integrations/vite/package-lock.json
generated
Normal file
@ -0,0 +1,274 @@
|
||||
{
|
||||
"name": "vite",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"vite": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.11.23",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.23.tgz",
|
||||
"integrity": "sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
|
||||
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.1.23",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
|
||||
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.2.15",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz",
|
||||
"integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.23",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.2.0",
|
||||
"path-parse": "^1.0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.48.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.48.0.tgz",
|
||||
"integrity": "sha512-wl9ZSSSsi5579oscSDYSzGn092tCS076YB+TQrzsGuSfYyJeep8eEWj0eaRjuC5McuMNmcnR8icBqiE/FWNB1A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.3.3.tgz",
|
||||
"integrity": "sha512-eO1iwRbn3/BfkNVMNJDeANAFCZ5NobYOFPu7IqfY7DcI7I9nFGjJIZid0EViTmLDGwwSUPmRAq3cRBbO3+DsMA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.11.23",
|
||||
"postcss": "^8.2.10",
|
||||
"resolve": "^1.19.0",
|
||||
"rollup": "^2.38.5"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"colorette": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.11.23",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.11.23.tgz",
|
||||
"integrity": "sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
|
||||
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.23",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
|
||||
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.2.15",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz",
|
||||
"integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colorette": "^1.2.2",
|
||||
"nanoid": "^3.1.23",
|
||||
"source-map": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.2.0",
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.48.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.48.0.tgz",
|
||||
"integrity": "sha512-wl9ZSSSsi5579oscSDYSzGn092tCS076YB+TQrzsGuSfYyJeep8eEWj0eaRjuC5McuMNmcnR8icBqiE/FWNB1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
},
|
||||
"vite": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.3.3.tgz",
|
||||
"integrity": "sha512-eO1iwRbn3/BfkNVMNJDeANAFCZ5NobYOFPu7IqfY7DcI7I9nFGjJIZid0EViTmLDGwwSUPmRAq3cRBbO3+DsMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.11.23",
|
||||
"fsevents": "~2.3.1",
|
||||
"postcss": "^8.2.10",
|
||||
"resolve": "^1.19.0",
|
||||
"rollup": "^2.38.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
integrations/vite/package.json
Normal file
20
integrations/vite/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "vite",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "./src/index.js",
|
||||
"browser": "./src/index.js",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "vite",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^2.3.3"
|
||||
}
|
||||
}
|
||||
5
integrations/vite/postcss.config.js
Normal file
5
integrations/vite/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
15
integrations/vite/tailwind.config.js
Normal file
15
integrations/vite/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
264
integrations/vite/tests/integration.test.js
Normal file
264
integrations/vite/tests/integration.test.js
Normal file
@ -0,0 +1,264 @@
|
||||
require('isomorphic-fetch')
|
||||
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
|
||||
output: 'dist',
|
||||
input: '.',
|
||||
})
|
||||
|
||||
let PORT = 1337
|
||||
|
||||
async function fetchCSS() {
|
||||
let response = await fetch(`http://0.0.0.0:${PORT}/index.css`, {
|
||||
headers: {
|
||||
Accept: 'text/css',
|
||||
},
|
||||
})
|
||||
return response.text()
|
||||
}
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold"></div>
|
||||
`
|
||||
)
|
||||
|
||||
await $('vite build', {
|
||||
env: { NODE_ENV: 'production' },
|
||||
})
|
||||
|
||||
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $(`vite --port ${PORT}`, {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
await runningProcess.onStdout((message) => message.includes('ready in'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold md:font-medium"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $(`vite --port ${PORT}`, {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
await runningProcess.onStdout((message) => message.includes('ready in'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await writeInputFile(
|
||||
'tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile(
|
||||
'index.html',
|
||||
html`
|
||||
<link rel="stylesheet" href="./index.css" />
|
||||
<div class="font-bold btn"></div>
|
||||
`
|
||||
)
|
||||
|
||||
let runningProcess = $(`vite --port ${PORT}`, {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
await runningProcess.onStdout((message) => message.includes('ready in'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
|
||||
|
||||
expect(await fetchCSS()).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
4
integrations/webpack-4/.gitignore
vendored
Normal file
4
integrations/webpack-4/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
9399
integrations/webpack-4/package-lock.json
generated
Normal file
9399
integrations/webpack-4/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
integrations/webpack-4/package.json
Normal file
25
integrations/webpack-4/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "webpack-4",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "./src/index.js",
|
||||
"browser": "./src/index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"dev": "webpack --mode=development",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "webpack 4",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^5.2.4",
|
||||
"mini-css-extract-plugin": "^1.6.0",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^4.7.0"
|
||||
}
|
||||
}
|
||||
5
integrations/webpack-4/postcss.config.js
Normal file
5
integrations/webpack-4/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
3
integrations/webpack-4/src/index.css
Normal file
3
integrations/webpack-4/src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
11
integrations/webpack-4/src/index.html
Normal file
11
integrations/webpack-4/src/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
integrations/webpack-4/src/index.js
Normal file
1
integrations/webpack-4/src/index.js
Normal file
@ -0,0 +1 @@
|
||||
import './index.css'
|
||||
15
integrations/webpack-4/tailwind.config.js
Normal file
15
integrations/webpack-4/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
236
integrations/webpack-4/tests/integration.test.js
Normal file
236
integrations/webpack-4/tests/integration.test.js
Normal file
@ -0,0 +1,236 @@
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
await $('webpack --mode=production')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
13
integrations/webpack-4/webpack.config.js
Normal file
13
integrations/webpack-4/webpack.config.js
Normal file
@ -0,0 +1,13 @@
|
||||
let MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
|
||||
module.exports = {
|
||||
plugins: [new MiniCssExtractPlugin()],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
4
integrations/webpack-5/.gitignore
vendored
Normal file
4
integrations/webpack-5/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
!tailwind.config.js
|
||||
!index.html
|
||||
3299
integrations/webpack-5/package-lock.json
generated
Normal file
3299
integrations/webpack-5/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
integrations/webpack-5/package.json
Normal file
25
integrations/webpack-5/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "webpack-5",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "./src/index.js",
|
||||
"browser": "./src/index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"dev": "webpack --mode=development",
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"displayName": "webpack 5",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"css-loader": "^5.2.4",
|
||||
"mini-css-extract-plugin": "^1.6.0",
|
||||
"postcss-loader": "^5.3.0",
|
||||
"webpack": "^5.37.0",
|
||||
"webpack-cli": "^4.7.0"
|
||||
}
|
||||
}
|
||||
5
integrations/webpack-5/postcss.config.js
Normal file
5
integrations/webpack-5/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
let path = require('path')
|
||||
|
||||
module.exports = {
|
||||
plugins: [require(path.resolve('..', '..'))],
|
||||
}
|
||||
3
integrations/webpack-5/src/index.css
Normal file
3
integrations/webpack-5/src/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
11
integrations/webpack-5/src/index.html
Normal file
11
integrations/webpack-5/src/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
integrations/webpack-5/src/index.js
Normal file
1
integrations/webpack-5/src/index.js
Normal file
@ -0,0 +1 @@
|
||||
import './index.css'
|
||||
15
integrations/webpack-5/tailwind.config.js
Normal file
15
integrations/webpack-5/tailwind.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
236
integrations/webpack-5/tests/integration.test.js
Normal file
236
integrations/webpack-5/tests/integration.test.js
Normal file
@ -0,0 +1,236 @@
|
||||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
await $('webpack --mode=production')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('watcher', () => {
|
||||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.font-normal {
|
||||
font-weight: 400;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
purge: ['./src/index.html'],
|
||||
mode: 'jit',
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
md: '800px'
|
||||
},
|
||||
fontWeight: {
|
||||
bold: 'bold'
|
||||
}
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.md\\:font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
|
||||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('webpack --mode=development --watch', {
|
||||
env: { TAILWIND_MODE: 'watch', TAILWIND_DISABLE_TOUCH: true },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
return runningProcess.stop()
|
||||
})
|
||||
})
|
||||
16
integrations/webpack-5/webpack.config.js
Normal file
16
integrations/webpack-5/webpack.config.js
Normal file
@ -0,0 +1,16 @@
|
||||
let MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
|
||||
module.exports = {
|
||||
plugins: [new MiniCssExtractPlugin()],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
|
||||
},
|
||||
],
|
||||
},
|
||||
output: {
|
||||
clean: true,
|
||||
},
|
||||
}
|
||||
@ -53,6 +53,48 @@ expect.extend({
|
||||
|
||||
return { actual: received, message, pass }
|
||||
},
|
||||
toIncludeCss(received, argument) {
|
||||
function stripped(str) {
|
||||
return str.replace(/\s/g, '').replace(/;/g, '')
|
||||
}
|
||||
|
||||
const options = {
|
||||
comment: 'stripped(received).includes(stripped(argument))',
|
||||
isNot: this.isNot,
|
||||
promise: this.promise,
|
||||
}
|
||||
|
||||
const pass = stripped(received).includes(stripped(argument))
|
||||
|
||||
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 actual = format(received)
|
||||
const expected = 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({
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
"prepublishOnly": "npm run babelify && ncc build lib/cli.js -o cli && babel-node scripts/build.js",
|
||||
"style": "eslint .",
|
||||
"test": "cross-env TAILWIND_MODE=build jest",
|
||||
"test:integrations": "npm run test --prefix ./integrations",
|
||||
"install:integrations": "node scripts/install-integrations.js",
|
||||
"posttest": "npm run style",
|
||||
"compat": "node scripts/compat.js --prepare",
|
||||
"compat:restore": "node scripts/compat.js --restore"
|
||||
@ -111,7 +113,8 @@
|
||||
"testTimeout": 30000,
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/jest/customMatchers.js"
|
||||
]
|
||||
],
|
||||
"testPathIgnorePatterns": ["/node_modules/", "/integrations/"]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
|
||||
27
scripts/install-integrations.js
Normal file
27
scripts/install-integrations.js
Normal file
@ -0,0 +1,27 @@
|
||||
let fs = require('fs/promises')
|
||||
let { spawn } = require('child_process')
|
||||
let path = require('path')
|
||||
let root = process.cwd()
|
||||
|
||||
function npmInstall(cwd) {
|
||||
return new Promise((resolve) => {
|
||||
let childProcess = spawn('npm', ['install'], { cwd })
|
||||
childProcess.on('exit', resolve)
|
||||
})
|
||||
}
|
||||
|
||||
async function install() {
|
||||
let base = path.resolve(root, 'integrations')
|
||||
let ignoreFolders = ['node_modules']
|
||||
let integrations = (await fs.readdir(base, { withFileTypes: true }))
|
||||
.filter((integration) => integration.isDirectory())
|
||||
.filter((integration) => !ignoreFolders.includes(integration.name))
|
||||
.map((folder) => path.resolve(base, folder.name))
|
||||
.concat([base])
|
||||
.map((integration) => npmInstall(integration))
|
||||
|
||||
await Promise.all(integrations)
|
||||
console.log('Done!')
|
||||
}
|
||||
|
||||
install()
|
||||
Loading…
x
Reference in New Issue
Block a user