tag as
- // an anchor for the styles to be placed before. These
- // styles will be applied _before_
+ >
+ )
+}
diff --git a/test/integration/scss-fixtures/with-styled-jsx/styles/global.scss b/test/integration/scss-fixtures/with-styled-jsx/styles/global.scss
new file mode 100644
index 0000000000000..30a5d888c5011
--- /dev/null
+++ b/test/integration/scss-fixtures/with-styled-jsx/styles/global.scss
@@ -0,0 +1,4 @@
+$var: red;
+.my-text {
+ color: $var;
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/_app.js b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/_app.js
new file mode 100644
index 0000000000000..0e40312aad8ac
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/_app.js
@@ -0,0 +1,5 @@
+import '../styles/global.scss'
+
+export default function MyApp({ Component, pageProps }) {
+ return
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/index.js b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/index.js
new file mode 100644
index 0000000000000..ee6a89480a706
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/pages/index.js
@@ -0,0 +1,38 @@
+import Link from 'next/link'
+
+const links = [
+ { href: 'https://github.com/zeit/next.js', label: 'GitHub' },
+ { href: 'https://nextjs.org/docs', label: 'Docs' },
+]
+
+function Nav() {
+ return (
+
+
+
+
+ Home
+
+
+
+ {links.map(({ href, label }) => (
+
+
+ {label}
+
+
+ ))}
+
+
+
+ )
+}
+
+export default () => (
+
+
+
+
Next.js + Tailwind CSS + PurgeCSS
+
+
+)
diff --git a/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/postcss.config.js b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/postcss.config.js
new file mode 100644
index 0000000000000..b39d3d7ff9d14
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/postcss.config.js
@@ -0,0 +1,13 @@
+const path = require('path')
+module.exports = {
+ plugins: [
+ 'tailwindcss',
+ [
+ '@fullhuman/postcss-purgecss',
+ {
+ content: [path.join(__dirname, './pages/**/*.{js,jsx,ts,tsx}')],
+ defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
+ },
+ ],
+ ],
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/styles/global.scss b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/styles/global.scss
new file mode 100644
index 0000000000000..b5c61c956711f
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss-and-purgecss/styles/global.scss
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/test/integration/scss-fixtures/with-tailwindcss/package.json b/test/integration/scss-fixtures/with-tailwindcss/package.json
new file mode 100644
index 0000000000000..50375a78eb20b
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss/package.json
@@ -0,0 +1,7 @@
+{
+ "postcss": {
+ "plugins": {
+ "tailwindcss": {}
+ }
+ }
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss/pages/_app.js b/test/integration/scss-fixtures/with-tailwindcss/pages/_app.js
new file mode 100644
index 0000000000000..0e40312aad8ac
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss/pages/_app.js
@@ -0,0 +1,5 @@
+import '../styles/global.scss'
+
+export default function MyApp({ Component, pageProps }) {
+ return
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss/pages/index.js b/test/integration/scss-fixtures/with-tailwindcss/pages/index.js
new file mode 100644
index 0000000000000..b3ba78da2d5e1
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss/pages/index.js
@@ -0,0 +1,3 @@
+export default function Home() {
+ return
+}
diff --git a/test/integration/scss-fixtures/with-tailwindcss/styles/global.scss b/test/integration/scss-fixtures/with-tailwindcss/styles/global.scss
new file mode 100644
index 0000000000000..b5c61c956711f
--- /dev/null
+++ b/test/integration/scss-fixtures/with-tailwindcss/styles/global.scss
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/test/integration/scss-modules/test/index.test.js b/test/integration/scss-modules/test/index.test.js
new file mode 100644
index 0000000000000..13b3c87f8ac5d
--- /dev/null
+++ b/test/integration/scss-modules/test/index.test.js
@@ -0,0 +1,450 @@
+/* eslint-env jest */
+/* global jasmine */
+import { join } from 'path'
+import { remove, readFile, readdir } from 'fs-extra'
+import {
+ nextBuild,
+ nextStart,
+ findPort,
+ killApp,
+ launchApp,
+ waitFor,
+ renderViaHTTP,
+} from 'next-test-utils'
+import cheerio from 'cheerio'
+import webdriver from 'next-webdriver'
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 1
+
+const fixturesDir = join(__dirname, '../../scss-fixtures')
+
+describe('Basic SCSS Module Support', () => {
+ const appDir = join(fixturesDir, 'basic-module')
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".index_redText__2VIiM{color:red}"`
+ )
+ })
+
+ it(`should've injected the CSS on server render`, async () => {
+ const content = await renderViaHTTP(appPort, '/')
+ const $ = cheerio.load(content)
+
+ const cssPreload = $('link[rel="preload"][as="style"]')
+ expect(cssPreload.length).toBe(1)
+ expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ const cssSheet = $('link[rel="stylesheet"]')
+ expect(cssSheet.length).toBe(1)
+ expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
+ `"index_redText__2VIiM"`
+ )
+ })
+})
+
+describe('3rd Party CSS Module Support', () => {
+ const appDir = join(fixturesDir, '3rd-party-module')
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".index_foo__9_fxH{position:relative}.index_foo__9_fxH .bar,.index_foo__9_fxH .baz{height:100%;overflow:hidden}.index_foo__9_fxH .lol,.index_foo__9_fxH>.lel{width:80%}"`
+ )
+ })
+
+ it(`should've injected the CSS on server render`, async () => {
+ const content = await renderViaHTTP(appPort, '/')
+ const $ = cheerio.load(content)
+
+ const cssPreload = $('link[rel="preload"][as="style"]')
+ expect(cssPreload.length).toBe(1)
+ expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ const cssSheet = $('link[rel="stylesheet"]')
+ expect(cssSheet.length).toBe(1)
+ expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
+ `"index_foo__9_fxH"`
+ )
+ })
+})
+
+describe('Has CSS Module in computed styles in Development', () => {
+ const appDir = join(fixturesDir, 'dev-module')
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have CSS for page', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('#verify-red')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
+ })
+})
+
+describe('Has CSS Module in computed styles in Production', () => {
+ const appDir = join(fixturesDir, 'prod-module')
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it('should have CSS for page', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('#verify-red')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
+ })
+})
+
+xdescribe('Can hot reload CSS Module without losing state', () => {
+ const appDir = join(fixturesDir, 'hmr-module')
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ // FIXME: this is broken
+ it('should update CSS color without remounting ', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ const desiredText = 'hello world'
+ await browser.elementById('text-input').type(desiredText)
+ expect(await browser.elementById('text-input').getValue()).toBe(desiredText)
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('#verify-red')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
+
+ const cssFile = new File(join(appDir, 'pages/index.module.scss'))
+ try {
+ cssFile.replace('color: red', 'color: purple')
+ await waitFor(2000) // wait for HMR
+
+ const refreshedColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('#verify-red')).color`
+ )
+ expect(refreshedColor).toMatchInlineSnapshot(`"rgb(128, 0, 128)"`)
+
+ // ensure text remained
+ expect(await browser.elementById('text-input').getValue()).toBe(
+ desiredText
+ )
+ } finally {
+ cssFile.restore()
+ }
+ })
+})
+
+describe('Invalid CSS Module Usage in node_modules', () => {
+ const appDir = join(fixturesDir, 'invalid-module')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('node_modules/example/index.module.scss')
+ expect(stderr).toMatch(
+ /CSS Modules.*cannot.*be imported from within.*node_modules/
+ )
+ expect(stderr).toMatch(/Location:.*node_modules[\\/]example[\\/]index\.mjs/)
+ })
+})
+
+describe('Invalid CSS Module Usage in node_modules', () => {
+ const appDir = join(fixturesDir, 'invalid-global-module')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('node_modules/example/index.scss')
+ expect(stderr).toMatch(
+ /Global CSS.*cannot.*be imported from within.*node_modules/
+ )
+ expect(stderr).toMatch(/Location:.*node_modules[\\/]example[\\/]index\.mjs/)
+ })
+})
+
+describe('Valid CSS Module Usage from within node_modules', () => {
+ const appDir = join(fixturesDir, 'nm-module')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've prerendered with relevant data`, async () => {
+ const content = await renderViaHTTP(appPort, '/')
+ const $ = cheerio.load(content)
+
+ const cssPreload = $('#nm-div')
+ expect(cssPreload.text()).toMatchInlineSnapshot(
+ `"{\\"message\\":\\"Why hello there\\"} {\\"redText\\":\\"example_redText__1hNNA\\"}"`
+ )
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".example_redText__1hNNA{color:red}"`
+ )
+ })
+})
+
+describe('Valid Nested CSS Module Usage from within node_modules', () => {
+ const appDir = join(fixturesDir, 'nm-module-nested')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've prerendered with relevant data`, async () => {
+ const content = await renderViaHTTP(appPort, '/')
+ const $ = cheerio.load(content)
+
+ const cssPreload = $('#nm-div')
+ expect(cssPreload.text()).toMatchInlineSnapshot(
+ `"{\\"message\\":\\"Why hello there\\"} {\\"other2\\":\\"example_other2__1pnJV\\",\\"subClass\\":\\"example_subClass__2EbKX other_className__E6nd8\\"}"`
+ )
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".other_other3__ZPN-Y{color:violet}.other_className__E6nd8{background:red;color:#ff0}.example_other2__1pnJV{color:red}.example_subClass__2EbKX{background:#00f}"`
+ )
+ })
+})
+
+describe('CSS Module Composes Usage (Basic)', () => {
+ // This is a very bad feature. Do not use it.
+ const appDir = join(fixturesDir, 'composes-basic')
+
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".index_className__2O8Wt{background:red;color:#ff0}.index_subClass__3e6Re{background:#00f}"`
+ )
+ })
+})
+
+describe('CSS Module Composes Usage (External)', () => {
+ // This is a very bad feature. Do not use it.
+ const appDir = join(fixturesDir, 'composes-external')
+
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
+ `".other_className__2VTl4{background:red;color:#ff0}.index_subClass__3e6Re{background:#00f}"`
+ )
+ })
+})
diff --git a/test/integration/scss/test/index.test.js b/test/integration/scss/test/index.test.js
new file mode 100644
index 0000000000000..d7dfd6b46b1c8
--- /dev/null
+++ b/test/integration/scss/test/index.test.js
@@ -0,0 +1,888 @@
+/* eslint-env jest */
+/* global jasmine */
+import 'flat-map-polyfill'
+import { join } from 'path'
+import { readdir, readFile, remove } from 'fs-extra'
+import {
+ findPort,
+ nextBuild,
+ nextStart,
+ launchApp,
+ killApp,
+ File,
+ waitFor,
+ renderViaHTTP,
+} from 'next-test-utils'
+import webdriver from 'next-webdriver'
+import cheerio from 'cheerio'
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
+
+const fixturesDir = join(__dirname, '../..', 'scss-fixtures')
+
+describe('SCSS Support', () => {
+ describe('Basic Global Support', () => {
+ const appDir = join(fixturesDir, 'single-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
+ 'color:red'
+ )
+ })
+ })
+
+ describe('Basic Global Support with src/ dir', () => {
+ const appDir = join(fixturesDir, 'single-global-src')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
+ 'color:red'
+ )
+ })
+ })
+
+ describe('Multi Global Support', () => {
+ const appDir = join(fixturesDir, 'multi-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(
+ cssContent.replace(/\/\*.*?\*\//g, '').trim()
+ ).toMatchInlineSnapshot(`".red-text{color:red}.blue-text{color:#00f}"`)
+ })
+ })
+
+ describe('Nested @import() Global Support', () => {
+ const appDir = join(fixturesDir, 'nested-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(
+ cssContent.replace(/\/\*.*?\*\//g, '').trim()
+ ).toMatchInlineSnapshot(
+ `".red-text{color:purple;font-weight:bolder;color:red}.blue-text{color:orange;font-weight:bolder;color:#00f}"`
+ )
+ })
+ })
+
+ describe('CSS Compilation and Prefixing', () => {
+ const appDir = join(fixturesDir, 'compilation-and-prefixing')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've compiled and prefixed`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(
+ cssContent.replace(/\/\*.*?\*\//g, '').trim()
+ ).toMatchInlineSnapshot(
+ `".redText ::-webkit-input-placeholder{color:red}.redText ::-moz-placeholder{color:red}.redText :-ms-input-placeholder{color:red}.redText ::-ms-input-placeholder{color:red}.redText ::placeholder{color:red}"`
+ )
+
+ // Contains a source map
+ expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
+ })
+
+ it(`should've emitted a source map`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssMapFiles = files.filter(f => /\.css\.map$/.test(f))
+
+ expect(cssMapFiles.length).toBe(1)
+ const cssMapContent = (
+ await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
+ ).trim()
+
+ const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
+ expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
+ Object {
+ "mappings": "AACA,qCAEI,SAHK,CACT,4BAEI,SAHK,CACT,gCAEI,SAHK,CACT,iCAEI,SAHK,CACT,uBAEI,SAHK",
+ "sourcesContent": Array [
+ "$var: red;
+ .redText {
+ ::placeholder {
+ color: $var;
+ }
+ }
+ ",
+ ],
+ "version": 3,
+ }
+ `)
+ })
+ })
+
+ // Tests css ordering
+ describe('Multi Global Support (reversed)', () => {
+ const appDir = join(fixturesDir, 'multi-global-reversed')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(
+ cssContent.replace(/\/\*.*?\*\//g, '').trim()
+ ).toMatchInlineSnapshot(`".blue-text{color:#00f}.red-text{color:red}"`)
+ })
+ })
+
+ describe('Invalid CSS in _document', () => {
+ const appDir = join(fixturesDir, 'invalid-module-document')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('styles.module.scss')
+ expect(stderr).toMatch(
+ /CSS.*cannot.*be imported within.*pages[\\/]_document\.js/
+ )
+ expect(stderr).toMatch(/Location:.*pages[\\/]_document\.js/)
+ })
+ })
+
+ describe('Invalid Global CSS', () => {
+ const appDir = join(fixturesDir, 'invalid-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('styles/global.scss')
+ expect(stderr).toMatch(
+ /Please move all global CSS imports.*?pages(\/|\\)_app/
+ )
+ expect(stderr).toMatch(/Location:.*pages[\\/]index\.js/)
+ })
+ })
+
+ describe('Invalid Global CSS with Custom App', () => {
+ const appDir = join(fixturesDir, 'invalid-global-with-app')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('styles/global.scss')
+ expect(stderr).toMatch(
+ /Please move all global CSS imports.*?pages(\/|\\)_app/
+ )
+ expect(stderr).toMatch(/Location:.*pages[\\/]index\.js/)
+ })
+ })
+
+ describe('Valid and Invalid Global CSS with Custom App', () => {
+ const appDir = join(fixturesDir, 'valid-and-invalid-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail to build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ })
+ expect(code).not.toBe(0)
+ expect(stderr).toContain('Failed to compile')
+ expect(stderr).toContain('styles/global.scss')
+ expect(stderr).toContain('Please move all global CSS imports')
+ expect(stderr).toMatch(/Location:.*pages[\\/]index\.js/)
+ })
+ })
+
+ describe('Can hot reload CSS without losing state', () => {
+ const appDir = join(fixturesDir, 'multi-page')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should update CSS color without remounting ', async () => {
+ let browser
+ try {
+ browser = await webdriver(appPort, '/page1')
+
+ const desiredText = 'hello world'
+ await browser.elementById('text-input').type(desiredText)
+ expect(await browser.elementById('text-input').getValue()).toBe(
+ desiredText
+ )
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.red-text')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
+
+ const cssFile = new File(join(appDir, 'styles/global1.scss'))
+ try {
+ cssFile.replace('$var: red', '$var: purple')
+ await waitFor(2000) // wait for HMR
+
+ const refreshedColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.red-text')).color`
+ )
+ expect(refreshedColor).toMatchInlineSnapshot(`"rgb(128, 0, 128)"`)
+
+ // ensure text remained
+ expect(await browser.elementById('text-input').getValue()).toBe(
+ desiredText
+ )
+ } finally {
+ cssFile.restore()
+ }
+ } finally {
+ if (browser) {
+ await browser.close()
+ }
+ }
+ })
+ })
+
+ describe('Has CSS in computed styles in Development', () => {
+ const appDir = join(fixturesDir, 'multi-page')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have CSS for page', async () => {
+ let browser
+ try {
+ browser = await webdriver(appPort, '/page2')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.blue-text')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
+ } finally {
+ if (browser) {
+ await browser.close()
+ }
+ }
+ })
+ })
+
+ describe('Body is not hidden when unused in Development', () => {
+ const appDir = join(fixturesDir, 'unused')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have body visible', async () => {
+ let browser
+ try {
+ browser = await webdriver(appPort, '/')
+ const currentDisplay = await browser.eval(
+ `window.getComputedStyle(document.querySelector('body')).display`
+ )
+ expect(currentDisplay).toBe('block')
+ } finally {
+ if (browser) {
+ await browser.close()
+ }
+ }
+ })
+ })
+
+ describe('Body is not hidden when broken in Development', () => {
+ const appDir = join(fixturesDir, 'unused')
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have body visible', async () => {
+ const pageFile = new File(join(appDir, 'pages/index.js'))
+ let browser
+ try {
+ pageFile.replace('
', '')
+ await waitFor(2000) // wait for recompile
+
+ browser = await webdriver(appPort, '/')
+ const currentDisplay = await browser.eval(
+ `window.getComputedStyle(document.querySelector('body')).display`
+ )
+ expect(currentDisplay).toBe('block')
+ } finally {
+ pageFile.restore()
+ if (browser) {
+ await browser.close()
+ }
+ }
+ })
+ })
+
+ describe('Has CSS in computed styles in Production', () => {
+ const appDir = join(fixturesDir, 'multi-page')
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it('should have CSS for page', async () => {
+ const browser = await webdriver(appPort, '/page2')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.blue-text')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
+ })
+
+ it(`should've preloaded the CSS file and injected it in `, async () => {
+ const content = await renderViaHTTP(appPort, '/page2')
+ const $ = cheerio.load(content)
+
+ const cssPreload = $('link[rel="preload"][as="style"]')
+ expect(cssPreload.length).toBe(1)
+ expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ const cssSheet = $('link[rel="stylesheet"]')
+ expect(cssSheet.length).toBe(1)
+ expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
+
+ /* ensure CSS preloaded first */
+ const allPreloads = [].slice.call($('link[rel="preload"]'))
+ const styleIndexes = allPreloads.flatMap((p, i) =>
+ p.attribs.as === 'style' ? i : []
+ )
+ expect(styleIndexes).toEqual([0])
+ })
+ })
+
+ describe('CSS URL via `file-loader`', () => {
+ const appDir = join(fixturesDir, 'url-global')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted expected files`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+ const mediaFolder = join(appDir, '.next/static/media')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
+ /^\.red-text\{color:red;background-image:url\(\/_next\/static\/media\/dark\.[a-z0-9]{32}\.svg\) url\(\/_next\/static\/media\/dark2\.[a-z0-9]{32}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/_next\/static\/media\/light\.[a-z0-9]{32}\.svg\);color:#00f\}$/
+ )
+
+ const mediaFiles = await readdir(mediaFolder)
+ expect(mediaFiles.length).toBe(3)
+ expect(
+ mediaFiles
+ .map(fileName =>
+ /^(.+?)\..{32}\.(.+?)$/
+ .exec(fileName)
+ .slice(1)
+ .join('.')
+ )
+ .sort()
+ ).toMatchInlineSnapshot(`
+ Array [
+ "dark.svg",
+ "dark2.svg",
+ "light.svg",
+ ]
+ `)
+ })
+ })
+
+ describe('CSS URL via `file-loader` and asset prefix (1)', () => {
+ const appDir = join(fixturesDir, 'url-global-asset-prefix-1')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted expected files`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+ const mediaFolder = join(appDir, '.next/static/media')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
+ /^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-z0-9]{32}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-z0-9]{32}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-z0-9]{32}\.svg\);color:#00f\}$/
+ )
+
+ const mediaFiles = await readdir(mediaFolder)
+ expect(mediaFiles.length).toBe(3)
+ expect(
+ mediaFiles
+ .map(fileName =>
+ /^(.+?)\..{32}\.(.+?)$/
+ .exec(fileName)
+ .slice(1)
+ .join('.')
+ )
+ .sort()
+ ).toMatchInlineSnapshot(`
+ Array [
+ "dark.svg",
+ "dark2.svg",
+ "light.svg",
+ ]
+ `)
+ })
+ })
+
+ describe('CSS URL via `file-loader` and asset prefix (2)', () => {
+ const appDir = join(fixturesDir, 'url-global-asset-prefix-2')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted expected files`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+ const mediaFolder = join(appDir, '.next/static/media')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
+ /^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-z0-9]{32}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-z0-9]{32}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-z0-9]{32}\.svg\);color:#00f\}$/
+ )
+
+ const mediaFiles = await readdir(mediaFolder)
+ expect(mediaFiles.length).toBe(3)
+ expect(
+ mediaFiles
+ .map(fileName =>
+ /^(.+?)\..{32}\.(.+?)$/
+ .exec(fileName)
+ .slice(1)
+ .join('.')
+ )
+ .sort()
+ ).toMatchInlineSnapshot(`
+ Array [
+ "dark.svg",
+ "dark2.svg",
+ "light.svg",
+ ]
+ `)
+ })
+ })
+
+ describe('Good CSS Import from node_modules', () => {
+ const appDir = join(fixturesDir, 'npm-import')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(/nprogress/)
+ })
+ })
+
+ describe('Good Nested CSS Import from node_modules', () => {
+ const appDir = join(fixturesDir, 'npm-import-nested')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've emitted a single CSS file`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+ expect(
+ cssContent.replace(/\/\*.*?\*\//g, '').trim()
+ ).toMatchInlineSnapshot(`".other{color:#00f}.test{color:red}"`)
+ })
+ })
+
+ describe('Bad CSS Import from node_modules', () => {
+ const appDir = join(fixturesDir, 'npm-import-bad')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should fail the build', async () => {
+ const { code, stderr } = await nextBuild(appDir, [], { stderr: true })
+
+ expect(code).not.toBe(0)
+ expect(stderr).toMatch(/Can't resolve '[^']*?nprogress[^']*?'/)
+ expect(stderr).toMatch(/Build error occurred/)
+ })
+ })
+
+ describe('Ordering with styled-jsx (dev)', () => {
+ const appDir = join(fixturesDir, 'with-styled-jsx')
+
+ let appPort
+ let app
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ appPort = await findPort()
+ app = await launchApp(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have the correct color (css ordering)', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.my-text')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 128, 0)"`)
+ })
+ })
+
+ describe('Ordering with styled-jsx (prod)', () => {
+ const appDir = join(fixturesDir, 'with-styled-jsx')
+
+ let appPort
+ let app
+ let stdout
+ let code
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ ;({ code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ }))
+ appPort = await findPort()
+ app = await nextStart(appDir, appPort)
+ })
+ afterAll(async () => {
+ await killApp(app)
+ })
+
+ it('should have compiled successfully', () => {
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it('should have the correct color (css ordering)', async () => {
+ const browser = await webdriver(appPort, '/')
+
+ const currentColor = await browser.eval(
+ `window.getComputedStyle(document.querySelector('.my-text')).color`
+ )
+ expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 128, 0)"`)
+ })
+ })
+
+ describe('Basic Tailwind CSS', () => {
+ const appDir = join(fixturesDir, 'with-tailwindcss')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've compiled and prefixed`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent).toMatch(/object-right-bottom/) // look for tailwind's CSS
+ expect(cssContent).not.toMatch(/tailwind/) // ensure @tailwind was removed
+
+ // Contains a source map
+ expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
+ })
+
+ it(`should've emitted a source map`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssMapFiles = files.filter(f => /\.css\.map$/.test(f))
+
+ expect(cssMapFiles.length).toBe(1)
+ })
+ })
+
+ describe('Tailwind and Purge CSS', () => {
+ const appDir = join(fixturesDir, 'with-tailwindcss-and-purgecss')
+
+ beforeAll(async () => {
+ await remove(join(appDir, '.next'))
+ })
+
+ it('should compile successfully', async () => {
+ const { code, stdout } = await nextBuild(appDir, [], {
+ stdout: true,
+ })
+ expect(code).toBe(0)
+ expect(stdout).toMatch(/Compiled successfully/)
+ })
+
+ it(`should've compiled and prefixed`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssFiles = files.filter(f => /\.css$/.test(f))
+
+ expect(cssFiles.length).toBe(1)
+ const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
+
+ expect(cssContent).not.toMatch(/object-right-bottom/) // this was unused and should be gone
+ expect(cssContent).toMatch(/text-blue-500/) // this was used
+ expect(cssContent).not.toMatch(/tailwind/) // ensure @tailwind was removed
+
+ // Contains a source map
+ expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
+ })
+
+ it(`should've emitted a source map`, async () => {
+ const cssFolder = join(appDir, '.next/static/css')
+
+ const files = await readdir(cssFolder)
+ const cssMapFiles = files.filter(f => /\.css\.map$/.test(f))
+
+ expect(cssMapFiles.length).toBe(1)
+ })
+ })
+})
diff --git a/test/integration/size-limit/test/index.test.js b/test/integration/size-limit/test/index.test.js
index 70fd0d332d00d..caedbdff0ec78 100644
--- a/test/integration/size-limit/test/index.test.js
+++ b/test/integration/size-limit/test/index.test.js
@@ -81,7 +81,7 @@ describe('Production response size', () => {
)
// These numbers are without gzip compression!
- const delta = responseSizeKilobytes - 235
+ const delta = responseSizeKilobytes - 233
expect(delta).toBeLessThanOrEqual(0) // don't increase size
expect(delta).toBeGreaterThanOrEqual(-1) // don't decrease size without updating target
})
@@ -101,7 +101,7 @@ describe('Production response size', () => {
)
// These numbers are without gzip compression!
- const delta = responseSizeKilobytes - 203
+ const delta = responseSizeKilobytes - 202
expect(delta).toBeLessThanOrEqual(0) // don't increase size
expect(delta).toBeGreaterThanOrEqual(-1) // don't decrease size without updating target
})
diff --git a/test/integration/typescript/components/router.tsx b/test/integration/typescript/components/router.tsx
index 21c1f80d15ea6..c33df8403d859 100644
--- a/test/integration/typescript/components/router.tsx
+++ b/test/integration/typescript/components/router.tsx
@@ -1,4 +1,4 @@
-/* eslint-disable no-unused-expressions */
+/* eslint-disable no-unused-expressions, @typescript-eslint/no-unused-expressions */
import React from 'react'
import Router, { withRouter } from 'next/router'
diff --git a/test/unit/handles-incorrect-react.test.js b/test/unit/handles-incorrect-react.test.js
index 965f0452a1ca9..32f5d53647b5f 100644
--- a/test/unit/handles-incorrect-react.test.js
+++ b/test/unit/handles-incorrect-react.test.js
@@ -11,7 +11,7 @@ const nextBin = path.join(nextDir, 'dist/bin/next')
describe('Handles Incorrect React Version', () => {
it('should throw an error when building with next', async () => {
expect(() => require(nextBin)).toThrow(
- /The version of React you are using is lower than the minimum required version needed for Next\.js\. Please upgrade "react" and "react-dom": "npm install --save react react-dom" https:\/\/err\.sh/
+ /The version of React you are using is lower than the minimum required version needed for Next\.js\. Please upgrade "react" and "react-dom": "npm install react react-dom" https:\/\/err\.sh/
)
})
})
diff --git a/yarn.lock b/yarn.lock
index 788305cc43a4e..9fb92865ae140 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -220,6 +220,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+"@babel/helper-plugin-utils@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670"
+ integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==
+
"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
@@ -384,6 +389,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
+"@babel/plugin-syntax-bigint@7.8.3":
+ version "7.8.3"
+ resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
+ integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
"@babel/plugin-syntax-dynamic-import@7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612"
@@ -2728,45 +2740,46 @@
dependencies:
"@types/yargs-parser" "*"
-"@typescript-eslint/eslint-plugin@2.6.1":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.6.1.tgz#e34972a24f8aba0861f9ccf7130acd74fd11e079"
- integrity sha512-Z0rddsGqioKbvqfohg7BwkFC3PuNLsB+GE9QkFza7tiDzuHoy0y823Y+oGNDzxNZrYyLjqkZtCTl4vCqOmEN4g==
+"@typescript-eslint/eslint-plugin@2.17.0":
+ version "2.17.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.17.0.tgz#880435a9f9bdd50b45fa286ba63fed723d73c837"
+ integrity sha512-tg/OMOtPeXlvk0ES8mZzEZ4gd1ruSE03nsKcK+teJhxYv5CPCXK6Mb/OK6NpB4+CqGTHs4MVeoSZXNFqpT1PyQ==
dependencies:
- "@typescript-eslint/experimental-utils" "2.6.1"
- eslint-utils "^1.4.2"
+ "@typescript-eslint/experimental-utils" "2.17.0"
+ eslint-utils "^1.4.3"
functional-red-black-tree "^1.0.1"
- regexpp "^2.0.1"
+ regexpp "^3.0.0"
tsutils "^3.17.1"
-"@typescript-eslint/experimental-utils@2.6.1":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.1.tgz#eddaca17a399ebf93a8628923233b4f93793acfd"
- integrity sha512-EVrrUhl5yBt7fC7c62lWmriq4MIc49zpN3JmrKqfiFXPXCM5ErfEcZYfKOhZXkW6MBjFcJ5kGZqu1b+lyyExUw==
+"@typescript-eslint/experimental-utils@2.17.0":
+ version "2.17.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.17.0.tgz#12ed4a5d656e02ff47a93efc7d1ce1b8f1242351"
+ integrity sha512-2bNf+mZ/3mj5/3CP56v+ldRK3vFy9jOvmCPs/Gr2DeSJh+asPZrhFniv4QmQsHWQFPJFWhFHgkGgJeRmK4m8iQ==
dependencies:
"@types/json-schema" "^7.0.3"
- "@typescript-eslint/typescript-estree" "2.6.1"
+ "@typescript-eslint/typescript-estree" "2.17.0"
eslint-scope "^5.0.0"
-"@typescript-eslint/parser@2.6.1":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.6.1.tgz#3c00116baa0d696bc334ca18ac5286b34793993c"
- integrity sha512-PDPkUkZ4c7yA+FWqigjwf3ngPUgoLaGjMlFh6TRtbjhqxFBnkElDfckSjm98q9cMr4xRzZ15VrS/xKm6QHYf0w==
+"@typescript-eslint/parser@2.17.0":
+ version "2.17.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.17.0.tgz#627f79586d868edbab55f46a6b183cdc341aea1d"
+ integrity sha512-k1g3gRQ4fwfJoIfgUpz78AovicSWKFANmvTfkAHP24MgJHjWfZI6ya7tsQZt1sLczvP4G9BE5G5MgADHdmJB/w==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
- "@typescript-eslint/experimental-utils" "2.6.1"
- "@typescript-eslint/typescript-estree" "2.6.1"
+ "@typescript-eslint/experimental-utils" "2.17.0"
+ "@typescript-eslint/typescript-estree" "2.17.0"
eslint-visitor-keys "^1.1.0"
-"@typescript-eslint/typescript-estree@2.6.1":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz#fb363dd4ca23384745c5ea4b7f4c867432b00d31"
- integrity sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==
+"@typescript-eslint/typescript-estree@2.17.0":
+ version "2.17.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.17.0.tgz#2ce1531ec0925ef8d22d7026235917c2638a82af"
+ integrity sha512-g0eVRULGnEEUakxRfJO0s0Hr1LLQqsI6OrkiCLpdHtdJJek+wyd8mb00vedqAoWldeDcOcP8plqw8/jx9Gr3Lw==
dependencies:
debug "^4.1.1"
- glob "^7.1.4"
+ eslint-visitor-keys "^1.1.0"
+ glob "^7.1.6"
is-glob "^4.0.1"
- lodash.unescape "4.0.1"
+ lodash "^4.17.15"
semver "^6.3.0"
tsutils "^3.17.1"
@@ -3030,6 +3043,17 @@ acorn@^7.1.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
+adjust-sourcemap-loader@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz#6471143af75ec02334b219f54bc7970c52fb29a4"
+ integrity sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==
+ dependencies:
+ assert "1.4.1"
+ camelcase "5.0.0"
+ loader-utils "1.2.3"
+ object-path "0.11.4"
+ regex-parser "2.2.10"
+
after-all-results@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/after-all-results/-/after-all-results-2.0.0.tgz#6ac2fc202b500f88da8f4f5530cfa100f4c6a2d0"
@@ -3236,6 +3260,11 @@ args@4.0.0:
leven "2.1.0"
mri "1.1.0"
+arity-n@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745"
+ integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U=
+
arr-diff@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
@@ -3283,7 +3312,7 @@ array-ify@^1.0.0:
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
-array-includes@^3.0.3:
+array-includes@^3.0.3, array-includes@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348"
integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==
@@ -3358,6 +3387,13 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+assert@1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+ integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=
+ dependencies:
+ util "0.10.3"
+
assert@^1.1.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
@@ -3371,6 +3407,11 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
+ast-types@0.13.2:
+ version "0.13.2"
+ resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48"
+ integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==
+
astral-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
@@ -4089,6 +4130,11 @@ camelcase@5.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
+camelcase@5.3.1, camelcase@^5.0.0, camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
camelcase@^2.0.0, camelcase@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
@@ -4104,11 +4150,6 @@ camelcase@^4.1.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-camelcase@^5.0.0, camelcase@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
- integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-
caniuse-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
@@ -4433,6 +4474,15 @@ clone-deep@^0.3.0:
kind-of "^3.2.2"
shallow-clone "^0.1.2"
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
clone-response@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
@@ -4588,6 +4638,13 @@ component-emitter@^1.2.0, component-emitter@^1.2.1:
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+compose-function@3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f"
+ integrity sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=
+ dependencies:
+ arity-n "^1.0.4"
+
compressible@~2.0.16:
version "2.0.18"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
@@ -4791,6 +4848,11 @@ convert-source-map@1.7.0, convert-source-map@^1.4.0, convert-source-map@^1.7.0:
dependencies:
safe-buffer "~5.1.1"
+convert-source-map@^0.3.3:
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
+ integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA=
+
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -5134,7 +5196,7 @@ css-what@^3.2.1:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1"
integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==
-css@2.2.4:
+css@2.2.4, css@^2.0.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
@@ -5290,6 +5352,14 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
+d@1, d@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
+ integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
+ dependencies:
+ es5-ext "^0.10.50"
+ type "^1.0.1"
+
dargs@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
@@ -5844,6 +5914,24 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
+es5-ext@^0.10.35, es5-ext@^0.10.50:
+ version "0.10.53"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
+ integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
+ dependencies:
+ es6-iterator "~2.0.3"
+ es6-symbol "~3.1.3"
+ next-tick "~1.0.0"
+
+es6-iterator@2.0.3, es6-iterator@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+ integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
+ dependencies:
+ d "1"
+ es5-ext "^0.10.35"
+ es6-symbol "^3.1.1"
+
es6-promise@^4.0.3, es6-promise@^4.1.1:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
@@ -5856,6 +5944,14 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
+es6-symbol@^3.1.1, es6-symbol@~3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
+ integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
+ dependencies:
+ d "^1.0.1"
+ ext "^1.1.2"
+
escape-goat@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-1.3.0.tgz#bf3ee8ad1e488fbba404b084b2e4a55e09231c64"
@@ -5888,25 +5984,25 @@ escodegen@^1.9.1:
optionalDependencies:
source-map "~0.6.1"
-eslint-plugin-react-hooks@2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.2.0.tgz#078264e9e388da6929ace09d6abe92c85963aff4"
- integrity sha512-jSlnBjV2cmyIeL555H/FbvuSbQ1AtpHjLMHuPrQnt1eVA6lX8yufdygh7AArI2m8ct7ChHGx2uOaCuxq2MUn6g==
+eslint-plugin-react-hooks@2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.3.0.tgz#53e073961f1f5ccf8dd19558036c1fac8c29d99a"
+ integrity sha512-gLKCa52G4ee7uXzdLiorca7JIQZPPXRAQDXV83J4bUEeUuc5pIEyZYAZ45Xnxe5IuupxEqHS+hUhSLIimK1EMw==
-eslint-plugin-react@7.16.0:
- version "7.16.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz#9928e4f3e2122ed3ba6a5b56d0303ba3e41d8c09"
- integrity sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==
+eslint-plugin-react@7.18.0:
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.18.0.tgz#2317831284d005b30aff8afb7c4e906f13fa8e7e"
+ integrity sha512-p+PGoGeV4SaZRDsXqdj9OWcOrOpZn8gXoGPcIQTzo2IDMbAKhNDnME9myZWqO3Ic4R3YmwAZ1lDjWl2R2hMUVQ==
dependencies:
- array-includes "^3.0.3"
+ array-includes "^3.1.1"
doctrine "^2.1.0"
has "^1.0.3"
- jsx-ast-utils "^2.2.1"
- object.entries "^1.1.0"
- object.fromentries "^2.0.0"
- object.values "^1.1.0"
+ jsx-ast-utils "^2.2.3"
+ object.entries "^1.1.1"
+ object.fromentries "^2.0.2"
+ object.values "^1.1.1"
prop-types "^15.7.2"
- resolve "^1.12.0"
+ resolve "^1.14.2"
eslint-scope@^4.0.3:
version "4.0.3"
@@ -5924,7 +6020,7 @@ eslint-scope@^5.0.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-utils@^1.4.2, eslint-utils@^1.4.3:
+eslint-utils@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
@@ -5936,10 +6032,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
-eslint@6.6.0:
- version "6.6.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.6.0.tgz#4a01a2fb48d32aacef5530ee9c5a78f11a8afd04"
- integrity sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==
+eslint@6.8.0:
+ version "6.8.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
+ integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
dependencies:
"@babel/code-frame" "^7.0.0"
ajv "^6.10.0"
@@ -5956,7 +6052,7 @@ eslint@6.6.0:
file-entry-cache "^5.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
- globals "^11.7.0"
+ globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
@@ -5969,7 +6065,7 @@ eslint@6.6.0:
minimatch "^3.0.4"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
- optionator "^0.8.2"
+ optionator "^0.8.3"
progress "^2.0.0"
regexpp "^2.0.1"
semver "^6.1.2"
@@ -5993,7 +6089,7 @@ esprima@^3.1.3:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
-esprima@^4.0.0:
+esprima@^4.0.0, esprima@~4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -6234,6 +6330,13 @@ express@^4.16.3:
utils-merge "1.0.1"
vary "~1.1.2"
+ext@^1.1.2:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
+ integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
+ dependencies:
+ type "^2.0.0"
+
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -7081,7 +7184,7 @@ glob-to-regexp@^0.4.1:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -7111,11 +7214,18 @@ global-prefix@^0.1.4:
is-windows "^0.2.0"
which "^1.2.12"
-globals@^11.1.0, globals@^11.7.0:
+globals@^11.1.0:
version "11.12.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+globals@^12.1.0:
+ version "12.3.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13"
+ integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==
+ dependencies:
+ type-fest "^0.8.1"
+
globby@^10.0.1:
version "10.0.2"
resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543"
@@ -8924,7 +9034,7 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.10.0"
-jsx-ast-utils@^2.2.1:
+jsx-ast-utils@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f"
integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==
@@ -9380,11 +9490,6 @@ lodash.toarray@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
-lodash.unescape@4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
- integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
-
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -10108,6 +10213,11 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0:
resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61"
integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==
+next-tick@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
+ integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
+
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
@@ -10556,6 +10666,11 @@ object-keys@~0.4.0:
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=
+object-path@0.11.4:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949"
+ integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=
+
object-visit@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
@@ -10573,7 +10688,7 @@ object.assign@^4.1.0:
has-symbols "^1.0.0"
object-keys "^1.0.11"
-object.entries@^1.1.0:
+object.entries@^1.1.0, object.entries@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b"
integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==
@@ -10583,7 +10698,7 @@ object.entries@^1.1.0:
function-bind "^1.1.1"
has "^1.0.3"
-object.fromentries@^2.0.0:
+object.fromentries@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9"
integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==
@@ -10616,7 +10731,7 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-object.values@^1.1.0:
+object.values@^1.1.0, object.values@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e"
integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==
@@ -10692,7 +10807,7 @@ optimize-css-assets-webpack-plugin@^5.0.1:
cssnano "^4.1.10"
last-call-webpack-plugin "^3.0.0"
-optionator@^0.8.1, optionator@^0.8.2:
+optionator@^0.8.1, optionator@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -12046,6 +12161,15 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1:
indexes-of "^1.0.1"
uniq "^1.0.1"
+postcss@7.0.21:
+ version "7.0.21"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17"
+ integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==
+ dependencies:
+ chalk "^2.4.2"
+ source-map "^0.6.1"
+ supports-color "^6.1.0"
+
postcss@^5.0.10:
version "5.2.18"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
@@ -12123,7 +12247,7 @@ pretty-hrtime@^1.0.3:
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=
-private@^0.1.6:
+private@^0.1.6, private@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
@@ -12646,6 +12770,16 @@ realpath-native@^1.1.0:
dependencies:
util.promisify "^1.0.0"
+recast@0.18.5:
+ version "0.18.5"
+ resolved "https://registry.yarnpkg.com/recast/-/recast-0.18.5.tgz#9d5adbc07983a3c8145f3034812374a493e0fe4d"
+ integrity sha512-sD1WJrpLQAkXGyQZyGzTM75WJvyAd98II5CHdK3IYbt/cZlU0UzCRVU11nUFNXX9fBVEt4E9ajkMjBlUlG+Oog==
+ dependencies:
+ ast-types "0.13.2"
+ esprima "~4.0.0"
+ private "^0.1.8"
+ source-map "~0.6.1"
+
redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -12719,11 +12853,21 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
+regex-parser@2.2.10:
+ version "2.2.10"
+ resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.10.tgz#9e66a8f73d89a107616e63b39d4deddfee912b37"
+ integrity sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==
+
regexpp@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
+regexpp@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e"
+ integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==
+
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
@@ -13021,6 +13165,22 @@ resolve-from@^4.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+resolve-url-loader@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz#28931895fa1eab9be0647d3b2958c100ae3c0bf0"
+ integrity sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ==
+ dependencies:
+ adjust-sourcemap-loader "2.0.0"
+ camelcase "5.3.1"
+ compose-function "3.0.3"
+ convert-source-map "1.7.0"
+ es6-iterator "2.0.3"
+ loader-utils "1.2.3"
+ postcss "7.0.21"
+ rework "1.0.1"
+ rework-visit "1.0.0"
+ source-map "0.6.1"
+
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -13045,6 +13205,13 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.8.1:
dependencies:
path-parse "^1.0.6"
+resolve@^1.14.2:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.0.tgz#1b7ca96073ebb52e741ffd799f6b39ea462c67f5"
+ integrity sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==
+ dependencies:
+ path-parse "^1.0.6"
+
responselike@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
@@ -13088,6 +13255,19 @@ reusify@^1.0.0:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+rework-visit@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a"
+ integrity sha1-mUWygD8hni96ygCtuLyfZA+ELJo=
+
+rework@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7"
+ integrity sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=
+ dependencies:
+ convert-source-map "^0.3.3"
+ css "^2.0.0"
+
rewrite-imports@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/rewrite-imports/-/rewrite-imports-1.4.0.tgz#198ebb73f59cfee8d214516c774b6aeef2c54a6e"
@@ -13245,6 +13425,17 @@ sass-loader@6.0.6:
lodash.tail "^4.1.1"
pify "^3.0.0"
+sass-loader@8.0.2:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d"
+ integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==
+ dependencies:
+ clone-deep "^4.0.1"
+ loader-utils "^1.2.3"
+ neo-async "^2.6.1"
+ schema-utils "^2.6.1"
+ semver "^6.3.0"
+
sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@@ -13275,6 +13466,14 @@ schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.6.0:
ajv "^6.10.2"
ajv-keywords "^3.4.1"
+schema-utils@^2.6.1:
+ version "2.6.4"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53"
+ integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==
+ dependencies:
+ ajv "^6.10.2"
+ ajv-keywords "^3.4.1"
+
scss-tokenizer@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
@@ -13432,6 +13631,13 @@ shallow-clone@^0.1.2:
lazy-cache "^0.2.3"
mixin-object "^2.0.1"
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -14647,6 +14853,16 @@ type-is@~1.6.17, type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
+type@^1.0.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
+ integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
+
+type@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3"
+ integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==
+
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"