Skip to content

Commit

Permalink
Try out support for ECMAScript modules (postcss#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael42 committed Mar 29, 2022
1 parent ee1e160 commit cd665f1
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 9 deletions.
33 changes: 32 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,32 @@ const createContext = (ctx) => {
return ctx
}

// prefers require, checks for ERR_REQUIRE_ESM, which is still experimental, but often works when called synchronous
const requireOrImport = filepath => {
try {
return require(filepath)
} catch (error) {
// importing ECMAScript modules from CommonJS does not work, so load it using dynamic import(...)
if (error.code === 'ERR_REQUIRE_ESM') {
return import(filepath).then(mod => mod.default)
}
throw error
}
}

// prefers import, which won't work in sync mode
const importOrRequire = async filepath => {
try {
return (await import(filepath)).default
} catch (error) {
// Node.js 10 does not support dynamic import(...) and throws 'Error: Not supported'
if (error.message === 'Not supported') {
return require(filepath)
}
throw error
}
}

const addTypeScriptLoader = (options = {}, loader) => {
const moduleName = 'postcss'

Expand All @@ -81,14 +107,19 @@ const addTypeScriptLoader = (options = {}, loader) => {
`.${moduleName}rc.ts`,
`.${moduleName}rc.js`,
`.${moduleName}rc.cjs`,
`.${moduleName}rc.mjs`,
`${moduleName}.config.ts`,
`${moduleName}.config.js`,
`${moduleName}.config.cjs`
`${moduleName}.config.cjs`,
`${moduleName}.config.mjs`
],
loaders: {
...options.loaders,
'.yaml': (filepath, content) => yaml.parse(content),
'.yml': (filepath, content) => yaml.parse(content),
'.js': requireOrImport,
'.cjs': requireOrImport,
'.mjs': requireOrImport,
'.ts': loader
}
}
Expand Down
80 changes: 72 additions & 8 deletions test/js.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ test('postcss.config.js - {Object} - Process SSS', () => {
})
})

describe('postcss.config.js - {Array} - Load Config', () => {
describe('postcss.config.js (CommonJS) - {Array} - Load Config', () => {
const ctx = {
parser: true,
syntax: true
Expand All @@ -88,27 +88,59 @@ describe('postcss.config.js - {Array} - Load Config', () => {
expect(typeof config.plugins[1]).toBe('object')

expect(config.file)
.toEqual(path.resolve('test/js/array', 'postcss.config.js'))
.toEqual(path.resolve('test/js/array/cjs-in-js', 'postcss.config.js'))
}

test('Async', () => {
return postcssrc(ctx, 'test/js/array').then(expected)
return postcssrc(ctx, 'test/js/array/cjs-in-js').then(expected)
})

test('Sync', () => {
const config = postcssrc.sync(ctx, 'test/js/array')
const config = postcssrc.sync(ctx, 'test/js/array/cjs-in-js')

expected(config)
})
})

test('postcss.config.js - {Array} - Process CSS', () => {
describe('postcss.config.cjs - {Array} - Load Config', () => {
const ctx = {
parser: true,
syntax: true
}

const expected = (config) => {
expect(config.options.parser).toEqual(require('sugarss'))
expect(config.options.syntax).toEqual(require('sugarss'))
expect(config.options.map).toEqual(false)
expect(config.options.from).toEqual('./test/js/array/fixtures/index.css')
expect(config.options.to).toEqual('./test/js/array/expect/index.css')

expect(config.plugins.length).toEqual(2)
expect(typeof config.plugins[0]).toBe('object')
expect(typeof config.plugins[1]).toBe('object')

expect(config.file)
.toEqual(path.resolve('test/js/array/cjs', 'postcss.config.cjs'))
}

test('Async', () => {
return postcssrc(ctx, 'test/js/array/cjs').then(expected)
})

test('Sync', () => {
const config = postcssrc.sync(ctx, 'test/js/array/cjs')

expected(config)
})
})

test('postcss.config.js (CommonJS) - {Array} - Process CSS', () => {
const ctx = {
parser: false,
syntax: false
}

return postcssrc(ctx, 'test/js/array').then((config) => {
return postcssrc(ctx, 'test/js/array/cjs').then((config) => {
return postcss(config.plugins)
.process(fixture('js/array', 'index.css'), config.options)
.then((result) => {
Expand All @@ -117,18 +149,50 @@ test('postcss.config.js - {Array} - Process CSS', () => {
})
})

test('postcss.config.js - {Array} - Process SSS', () => {
test('postcss.config.js (CommonJS) - {Array} - Process SSS', () => {
const ctx = {
from: './test/js/array/fixtures/index.sss',
parser: true,
syntax: false
}

return postcssrc(ctx, 'test/js/array').then((config) => {
return postcssrc(ctx, 'test/js/array/cjs').then((config) => {
return postcss(config.plugins)
.process(fixture('js/array', 'index.sss'), config.options)
.then((result) => {
expect(result.css).toEqual(expected('js/array', 'index.sss'))
})
})
})

describe('postcss.config.mjs - {Array} - Load Config', () => {
const ctx = {
parser: true,
syntax: true
}

const expected = (config) => {
expect(config.options.parser).toEqual(require('sugarss'))
expect(config.options.syntax).toEqual(require('sugarss'))
expect(config.options.map).toEqual(false)
expect(config.options.from).toEqual('./test/js/array/fixtures/index.css')
expect(config.options.to).toEqual('./test/js/array/expect/index.css')

expect(config.plugins.length).toEqual(2)
expect(typeof config.plugins[0]).toBe('object')
expect(typeof config.plugins[1]).toBe('object')

expect(config.file)
.toEqual(path.resolve('test/js/array/mjs', 'postcss.config.mjs'))
}

test('Async', () => {
return postcssrc(ctx, 'test/js/array/mjs').then(expected)
})

xtest('Sync', () => {
const config = postcssrc.sync(ctx, 'test/js/array/mjs')

expected(config)
})
})
File renamed without changes.
14 changes: 14 additions & 0 deletions test/js/array/cjs/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = function (ctx) {
return {
parser: ctx.parser ? 'sugarss' : false,
syntax: ctx.syntax ? 'sugarss' : false,
map: ctx.map ? 'inline' : false,
from: './test/js/array/fixtures/index.css',
to: './test/js/array/expect/index.css',
plugins: [
require('postcss-import')(),
require('postcss-nested')(),
ctx.env === 'production' ? require('cssnano')() : false
]
}
}
1 change: 1 addition & 0 deletions test/js/array/esm-in-js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type": "module"}
18 changes: 18 additions & 0 deletions test/js/array/esm-in-js/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import postcssImport from 'postcss-import'
import postcssNested from 'postcss-nested'
import cssnano from 'cssnano'

export default function (ctx) {
return {
parser: ctx.parser ? 'sugarss' : false,
syntax: ctx.syntax ? 'sugarss' : false,
map: ctx.map ? 'inline' : false,
from: './test/js/array/fixtures/index.css',
to: './test/js/array/expect/index.css',
plugins: [
postcssImport(),
postcssNested(),
ctx.env === 'production' ? cssnano() : false
]
}
}
18 changes: 18 additions & 0 deletions test/js/array/mjs/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import postcssImport from 'postcss-import'
import postcssNested from 'postcss-nested'
import cssnano from 'cssnano'

export default function (ctx) {
return {
parser: ctx.parser ? 'sugarss' : false,
syntax: ctx.syntax ? 'sugarss' : false,
map: ctx.map ? 'inline' : false,
from: './test/js/array/fixtures/index.css',
to: './test/js/array/expect/index.css',
plugins: [
postcssImport(),
postcssNested(),
ctx.env === 'production' ? cssnano() : false
]
}
}
14 changes: 14 additions & 0 deletions test/js/object/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function (ctx) {
return {
parser: ctx.parser ? 'sugarss' : false,
syntax: ctx.syntax ? 'sugarss' : false,
map: ctx.map ? 'inline' : false,
from: './test/js/object/fixtures/index.css',
to: './test/js/object/expect/index.css',
plugins: {
'postcss-import': {},
'postcss-nested': {},
cssnano: ctx.env === 'production' ? {} : false
}
}
}

0 comments on commit cd665f1

Please sign in to comment.