diff --git a/README.md b/README.md index 4c8a151..15d2663 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,16 @@ module.exports = { */ resolveURL: true, // resolveURL: { nocheck: true }, + + /** + * Move @import and @charset to the top. + * + * @see https://stylus-lang.com/docs/executable.html + * + * @type {boolean} + * @default false + */ + hoistAtrules: true, }, }, }, diff --git a/src/index.js b/src/index.js index e1da1f0..2f9c8dc 100644 --- a/src/index.js +++ b/src/index.js @@ -41,6 +41,10 @@ export default async function stylusLoader(source) { styl.set('include css', true); } + if (stylusOptions.hoistAtrules) { + styl.set('hoist atrules', true); + } + if (stylusOptions.disableCache) { styl.set('cache', false); } diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap index 47c5968..8376120 100644 --- a/test/__snapshots__/loader.test.js.snap +++ b/test/__snapshots__/loader.test.js.snap @@ -689,6 +689,18 @@ exports[`loader should work "define" option: errors 1`] = `Array []`; exports[`loader should work "define" option: warnings 1`] = `Array []`; +exports[`loader should work "hoistAtrules" option: css 1`] = ` +"@charset 'utf-8'; +body { + color: #f00; +} +" +`; + +exports[`loader should work "hoistAtrules" option: errors 1`] = `Array []`; + +exports[`loader should work "hoistAtrules" option: warnings 1`] = `Array []`; + exports[`loader should work "include" option: css 1`] = ` ".other { font-family: serif; diff --git a/test/fixtures/hoist-atrules.styl b/test/fixtures/hoist-atrules.styl new file mode 100644 index 0000000..96b5ad0 --- /dev/null +++ b/test/fixtures/hoist-atrules.styl @@ -0,0 +1,4 @@ +body + color: red + +@charset 'utf-8'; diff --git a/test/helpers/getCodeFromStylus.js b/test/helpers/getCodeFromStylus.js index 452d748..aff11a4 100644 --- a/test/helpers/getCodeFromStylus.js +++ b/test/helpers/getCodeFromStylus.js @@ -111,6 +111,10 @@ async function getCodeFromStylus(testId, options = {}) { : `${options.additionalData}\n${data}`; } + if (typeof stylusOptions.hoistAtrules === 'boolean') { + stylusOptions['hoist atrules'] = stylusOptions.hoistAtrules; + } + const mergedOptions = { ...defaultOptions, ...stylusOptions, diff --git a/test/loader.test.js b/test/loader.test.js index 1ec6f0b..13957f8 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -1263,6 +1263,27 @@ describe('loader', () => { expect(getErrors(stats)).toMatchSnapshot('errors'); }); + it('should work "hoistAtrules" option', async () => { + const testId = './hoist-atrules.styl'; + const compiler = getCompiler(testId, { + stylusOptions: { + hoistAtrules: true, + }, + }); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle(stats, compiler); + const codeFromStylus = await getCodeFromStylus(testId, { + stylusOptions: { + hoistAtrules: true, + }, + }); + + expect(codeFromBundle.css).toBe(codeFromStylus.css); + expect(codeFromBundle.css).toMatchSnapshot('css'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + it('should use .json file', async () => { const testId = './json/index.styl'; const compiler = getCompiler(testId, {