Skip to content

Commit

Permalink
Pass sass options to plugin (#1308)
Browse files Browse the repository at this point in the history
* Pass sass options to plugin

* Rename Sass options -> compilerOptions

* Typo

* Fix string

* Update README
  • Loading branch information
drwpow committed Oct 15, 2020
1 parent 338e4e9 commit b2d7e37
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
23 changes: 20 additions & 3 deletions plugins/plugin-sass/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ module.exports = {

## Plugin Options

| Name | Type | Description |
| :------- | :-------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `native` | `boolean` | If true, the plugin will ignore the npm version of sass installed locally for the native Sass CLI [installed separately](https://sass-lang.com/install). This involves extra set up, but the result can be [up to 9x faster.](https://stackoverflow.com/a/56422541) Defaults to false. |
| Name | Type | Description |
| :------------------ | :-------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `native` | `boolean` | If `true`, the plugin will ignore the npm version of sass installed locally for the native Sass CLI [installed separately](https://sass-lang.com/install). This involves extra setup, but the result can be [up to 9× faster.](https://stackoverflow.com/a/56422541) (default: `false`). |
| `compilerOptions.*` | `object` | Pass [Sass options][sass-options] directly to the Sass compiler (see `compilerOptions`). |

### `compilerOptions`

These options are camelCased equivalents of the [Sass CLI Options][sass-options]. The options listed here are safe for use. The other flags not listed here may cause issues or conflicts with Snowpack and/or other plugins; use at your discretion.

| Name | Type | Description |
| :--------------- | :----------------------------: | :------------------------------------------------------------------------------------------------------ |
| `style` | `'expanded'` \| `'compressed'` | The output style. Specify `'compressed'` to enable Sass’ built-in minification (default: `'expanded'`). |
| `sourceMap` | `boolean` | Enable / disable source maps (default: `true`). |
| `sourceMapUrls` | `'relative'` \| `'absolute'` | How to link from source maps to source files (default: `'relative'`). |
| `embedSources` | `boolean` | Embed source file contents in source maps (default: `false`). |
| `embedSourceMap` | `boolean` | Embed source map contents in CSS (default: `false`). |
| `charset` | `boolean` | Emit a `@charset` or BOM for CSS with non-ASCII characters. (default: `true`). |
| `update` | `boolean` | Only compile out-of-date stylesheets (default: `false`). |

[sass-options]: https://sass-lang.com/documentation/cli/dart-sass#options
20 changes: 19 additions & 1 deletion plugins/plugin-sass/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function scanSassImports(fileContents, filePath, fileExt) {
});
}

module.exports = function postcssPlugin(_, {native}) {
module.exports = function sassPlugin(_, {native, compilerOptions = {}} = {}) {
/** A map of partially resolved imports to the files that imported them. */
const importedByMap = new Map();

Expand Down Expand Up @@ -89,11 +89,29 @@ module.exports = function postcssPlugin(_, {native}) {
const sassImports = scanSassImports(contents, filePath, fileExt);
sassImports.forEach((imp) => addImportsToMap(filePath, imp));
}

// If file is `.sass`, use YAML-style. Otherwise, use default.
const args = ['--stdin', '--load-path', path.dirname(filePath)];
if (fileExt === '.sass') {
args.push('--indented');
}

// Pass in user-defined options
Object.entries(compilerOptions).forEach(([flag, value]) => {
let flagName = flag.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`); // convert camelCase to kebab-case
switch (typeof value) {
case 'boolean': {
args.push(`--${value === false ? 'no-' : ''}${flagName}`);
break;
}
case 'string':
case 'number': {
args.push(`--${flagName}=${value}`);
break;
}
}
});

// Build the file.
const {stdout, stderr} = await execa('sass', args, {
input: contents,
Expand Down
47 changes: 47 additions & 0 deletions plugins/plugin-sass/test/plugin-mocked.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* This test requires mocks which could disrupt other tests
*/
const path = require('path');
const mockExeca = jest.fn().mockImplementation(() => Promise.resolve({stdout: '', stderr: ''}));
jest.mock('execa', () => (cmd, args) => mockExeca(cmd, args));
const plugin = require('../plugin');

const MOCK_CONFIG = null;
const MOCK_LOAD = {filePath: path.join(__dirname, 'fixtures', 'scss', 'App.scss'), isDev: false};

const tests = [
{name: 'no options', given: {}, expect: []},
{
name: 'string option',
given: {compilerOptions: {style: 'compressed'}},
expect: [`--style=compressed`],
},
{
name: 'boolean option',
given: {compilerOptions: {sourceMaps: false}},
expect: [`--no-source-maps`],
},
{
name: 'combination',
given: {compilerOptions: {style: 'compressed', sourceMaps: true}},
expect: [`--style=compressed`, `--source-maps`],
},
];

describe('plugin-sass', () => {
afterEach(() => {
mockExeca.mockClear(); // clear calls between each test
});

tests.forEach((t) => {
it(t.name, async () => {
const {load} = plugin(MOCK_CONFIG, t.given);
await load(MOCK_LOAD);
// Note: this test assumes execa is only used once in the entire plugin.
// If execa needs to be used for another purpose, you can filter calls by 'sass' 1st param here
t.expect.forEach((arg) => {
expect(mockExeca.mock.calls[0][1]).toContain(arg);
});
});
});
});

1 comment on commit b2d7e37

@vercel
Copy link

@vercel vercel bot commented on b2d7e37 Oct 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.