diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b6a04c9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root=true + +[*] +charset = utf-8 +indent_size = 2 +indent_style = tab +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/index.js b/index.js new file mode 100644 index 0000000..e050d91 --- /dev/null +++ b/index.js @@ -0,0 +1,122 @@ +const regexDoc = /pages[\\/]_document\./ +const regexLikeCss = /\.(css|scss|sass)$/ +const regexMoreLikeCss = /\.(css|scss|sass|styl|less)$/ +const regexCssGlobal = /(? (a, c) => { + const { context: ctx, stylusOptions, lessOptions} = config + + const stylusLoader = { + loader: 'stylus-loader', + options: { sourceMap: true, stylusOptions } + } + const lessLoader = { + loader: 'less-loader', + options: { sourceMap: true, lessOptions} + } + + const matchesRegExpTest = 'test' in c + && c.test instanceof RegExp + && c.test.source + + const matchesRegExpIssuer = 'issuer' in c + && c.issuer instanceof RegExp + && c.issuer.source + + const regStrArr = a => a + .map(t => `${t instanceof RegExp ? 'r' : 's'}>>${t}`) + .sort() + .join() + + const matchArray = a => b => regStrArr(a) === regStrArr(b) + + const testAccepts = ('test' in c + && Array.isArray(c.test) + && matchArray(c.test) + || (() => false)) + + const issuerAccepts = ('issuer' in c + && 'and' in c.issuer + && Array.isArray(c.issuer.and) + && matchArray(c.issuer.and) + || (() => false)) + + const issuerAvoids = ('issuer' in c + && 'not' in c.issuer + && Array.isArray(c.issuer.not) + && matchArray(c.issuer.not) + || (() => false)) + + if (matchesRegExpTest === regexLikeCss.source && matchesRegExpIssuer === regexDoc.source) { + c = [{ ...c, test: regexMoreLikeCss }] + return [].concat(a, c) + } + + if (matchesRegExpTest === regexSassModules.source && issuerAccepts([ctx]) && issuerAvoids([/node_modules/])) { + c = [ c, + { ...c, test: regexStylusModules, use: [].concat(...c.use.slice(0, -1), stylusLoader) }, + { ...c, test: regexLessModules, use: [].concat(...c.use.slice(0, -1), lessLoader) }, + ] + return [].concat(a, c) + } + + if (testAccepts([regexCssModules, regexSassModules])) { + c = [{ ...c, test: [].concat(c.test, regexStylusModules, regexLessModules) }] + return [].concat(a, c) + } + + // A bit of a hacky way to check custom _App file ... but async/promise isn't allowed in NextJS configs so yeah. + if (matchesRegExpTest === regexSassGlobal.source && issuerAccepts([ c.issuer && c.issuer.and && /_app\./.test(c.issuer.and.join()) && c.issuer.and ])) { + c = [ c, + { ...c, test: regexStylusGlobal, use: [].concat(...c.use.slice(0, -1), stylusLoader) }, + { ...c, test: regexLessGlobal, use: [].concat(...c.use.slice(0, -1), lessLoader) }, + ] + return [].concat(a, c) + } + + if (testAccepts([regexCssGlobal, regexSassGlobal]) && issuerAccepts([/node_modules/])) { + c = [{ ...c, test: [].concat(c.test, regexStylusGlobal, regexLessGlobal) }] + return [].concat(a, c) + } + + if (testAccepts([regexCssGlobal, regexSassGlobal])) { + c = [{ ...c, test: [].concat(c.test, regexStylusGlobal, regexLessGlobal) }] + return [].concat(a, c) + } + + if (matchesRegExpIssuer === regexLikeCss.source) { + c = [{ ...c, issuer: regexMoreLikeCss }] + return [].concat(a, c) + } + + return [].concat(a, c) +} + +module.exports = (nextConfig = {}) => ({ + ...nextConfig, + webpack(config, options) { + const rules = config.module.rules.map(rule => 'oneOf' in rule + ? ({ ...rule, oneOf: rule.oneOf.reduce(ammendOneOfRules(config)) }) + : rule + ) + config.module.rules = rules + + if (typeof nextConfig.webpack === 'function') { + config = nextConfig.webpack(config, options) + } + return config + }, + webpackDevMiddleware(config, options) { + if (typeof nextConfig.webpackDevMiddleware === 'function') + config = nextConfig.webpackDevMiddleware(config, options) + + return config + } +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..6f4416d --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "next-pre-css", + "version": "1.0.0", + "description": "Adds support for Stylus & Less to NextJS.", + "main": "index.js", + "repository": "git@github.com:eshinn/next-pre-css.git", + "author": "Eric Shinn ", + "license": "MIT", + "private": true +}