diff --git a/src/assets/LESSAsset.js b/src/assets/LESSAsset.js index fc47a0657d2..a915de719e7 100644 --- a/src/assets/LESSAsset.js +++ b/src/assets/LESSAsset.js @@ -1,6 +1,10 @@ const Asset = require('../Asset'); const localRequire = require('../utils/localRequire'); const promisify = require('../utils/promisify'); +const Resolver = require('../Resolver'); +const syncPromise = require('../utils/syncPromise'); +const fs = require('../utils/fs'); +const path = require('path'); class LESSAsset extends Asset { constructor(name, options) { @@ -54,8 +58,39 @@ function urlPlugin(asset) { visitor.run = visitor.visit; pluginManager.addVisitor(visitor); + + let LessFileManager = getFileManager(less, asset.options); + pluginManager.addFileManager(new LessFileManager()); } }; } +function getFileManager(less, options) { + const resolver = new Resolver({ + extensions: ['.css', '.less'], + rootDir: options.rootDir + }); + + class LessFileManager extends less.FileManager { + async resolve(filename, currentDirectory) { + return (await resolver.resolve( + filename, + path.join(currentDirectory, 'index') + )).path; + } + + async loadFile(filename, currentDirectory) { + filename = await this.resolve(filename, currentDirectory); + let contents = await fs.readFile(filename, 'utf8'); + return {contents, filename}; + } + + loadFileSync(filename, currentDirectory) { + return syncPromise(this.loadFile(filename, currentDirectory)); + } + } + + return LessFileManager; +} + module.exports = LESSAsset; diff --git a/test/integration/less-advanced-import/base.less b/test/integration/less-advanced-import/base.less new file mode 100644 index 00000000000..00b74d20da2 --- /dev/null +++ b/test/integration/less-advanced-import/base.less @@ -0,0 +1,5 @@ +@base: #f938ab; + +.base { + color: @base; +} diff --git a/test/integration/less-advanced-import/index.js b/test/integration/less-advanced-import/index.js new file mode 100644 index 00000000000..dc0bb37def5 --- /dev/null +++ b/test/integration/less-advanced-import/index.js @@ -0,0 +1,5 @@ +require('~/index.less'); + +module.exports = function () { + return 2; +}; diff --git a/test/integration/less-advanced-import/index.less b/test/integration/less-advanced-import/index.less new file mode 100644 index 00000000000..46f03947c99 --- /dev/null +++ b/test/integration/less-advanced-import/index.less @@ -0,0 +1,5 @@ +@import '~/base.less'; + +.index { + color: @base; +} diff --git a/test/less.js b/test/less.js index 06c07f1d1b1..b42caaf660f 100644 --- a/test/less.js +++ b/test/less.js @@ -56,6 +56,35 @@ describe('less', function() { assert(css.includes('.base')); }); + it('should support advanced less imports', async function() { + let b = await bundle( + __dirname + '/integration/less-advanced-import/index.js' + ); + + assertBundleTree(b, { + name: 'index.js', + assets: ['index.js', 'index.less'], + childBundles: [ + { + type: 'map' + }, + { + name: 'index.css', + assets: ['index.less'], + childBundles: [] + } + ] + }); + + let output = run(b); + assert.equal(typeof output, 'function'); + assert.equal(output(), 2); + + let css = fs.readFileSync(__dirname + '/dist/index.css', 'utf8'); + assert(css.includes('.index')); + assert(css.includes('.base')); + }); + it('should support requiring empty less files', async function() { let b = await bundle(__dirname + '/integration/less-empty/index.js');