Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: export a decoupled version of the Sass importer
This will be used by `vue-jest` and potentially other projects, to write a Jest transform that can adequately mimic `sass-loader`'s behaviour. Closes #873
- Loading branch information
Showing
5 changed files
with
194 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { getSassImplementation, getWebpackResolver } from './utils'; | ||
|
||
/** | ||
* A factory function for creating a Sass importer that uses `sass-loader`'s | ||
* resolution rules. | ||
* | ||
* @see https://sass-lang.com/documentation/js-api#importer | ||
* | ||
* This is useful when attempting to mimic `sass-loader`'s behaviour in contexts | ||
* that do not support Webpack. For example, it could be used to write a Jest | ||
* transform for testing files with Sass imports. | ||
* | ||
* The resulting Sass importer is asynchronous, so it can only be used with | ||
* `sass.render()` and not `renderSync()`. | ||
* | ||
* Example usage: | ||
* ```js | ||
* import sass from 'sass'; | ||
* import resolve from 'enhanced-resolve'; | ||
* import createImporter from 'sass-loader/dist/importer'; | ||
* import webpackConfig = './webpack.config'; | ||
* | ||
* const { resolve: { alias } } = webpackConfig; | ||
* const resolverFactory = (options) => resolve.create({ alias, ...options }); | ||
* const importer = createImporter(resolverFactory, sass); | ||
* | ||
* sass.render({ | ||
* file: 'input.scss', | ||
* importer, | ||
* }, (err, result) => { | ||
* // ... | ||
* }); | ||
* ``` | ||
* | ||
* @param {Function} resolverFactory - A factory function for creating a Webpack | ||
* resolver. The resulting `resolve` function should be compatible with the | ||
* asynchronous resolve function supplied by [`enhanced-resolve`]{@link | ||
* https://github.com/webpack/enhanced-resolve}. In all likelihood you'll want | ||
* to pass `resolve.create()` from `enhanced-resolve`, or a wrapped copy of | ||
* it. | ||
* @param {Object} [implementation] - The imported Sass implementation, both | ||
* `sass` (Dart Sass) and `node-sass` are supported. If no implementation is | ||
* supplied, `sass` will be preferred if it's available. | ||
* @param {string[]} [includePaths] - The list of include paths passed to Sass. | ||
* | ||
* @returns {Function} | ||
*/ | ||
export default function createSassImporter( | ||
resolverFactory, | ||
implementation = null, | ||
includePaths = [] | ||
) { | ||
if (!implementation) { | ||
// eslint-disable-next-line no-param-reassign | ||
implementation = getSassImplementation(); | ||
} | ||
|
||
const resolve = getWebpackResolver( | ||
implementation, | ||
resolverFactory, | ||
includePaths | ||
); | ||
|
||
return (url, prev, done) => { | ||
resolve(prev, url) | ||
.then((result) => { | ||
done({ file: result }); | ||
}) | ||
.catch(() => { | ||
done(null); | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`importer should resolve imports when passed to \`sass\` 1`] = ` | ||
"@charset \\"UTF-8\\"; | ||
/* @import another/module */ | ||
@import url(http://example.com/something/from/the/interwebs); | ||
.another-sass-module { | ||
background: hotpink; | ||
} | ||
/* @import another/underscore */ | ||
.underscore { | ||
background: hotpink; | ||
} | ||
/* @import another/_underscore */ | ||
.underscore { | ||
background: hotpink; | ||
} | ||
/* @import ~sass/underscore */ | ||
.underscore-sass { | ||
background: hotpink; | ||
} | ||
/* @import ~sass/some.module */ | ||
.some-sass-module { | ||
background: hotpink; | ||
} | ||
/* @import url(http://example.com/something/from/the/interwebs); */ | ||
/* scoped import @import language */ | ||
.scoped-import body { | ||
font: 100% Helvetica, sans-serif; | ||
color: #333; | ||
} | ||
.scoped-import nav ul { | ||
margin: 0; | ||
padding: 0; | ||
list-style: none; | ||
} | ||
.scoped-import nav li { | ||
display: inline-block; | ||
} | ||
.scoped-import nav a { | ||
display: block; | ||
padding: 6px 12px; | ||
text-decoration: none; | ||
} | ||
.scoped-import .box { | ||
-webkit-border-radius: 10px; | ||
-moz-border-radius: 10px; | ||
-ms-border-radius: 10px; | ||
border-radius: 10px; | ||
} | ||
.scoped-import .message, .scoped-import .warning, .scoped-import .error, .scoped-import .success { | ||
border: 1px solid #ccc; | ||
padding: 10px; | ||
color: #333; | ||
} | ||
.scoped-import .success { | ||
border-color: green; | ||
} | ||
.scoped-import .error { | ||
border-color: red; | ||
} | ||
.scoped-import .warning { | ||
border-color: yellow; | ||
} | ||
.scoped-import .foo:before { | ||
content: \\"\\"; | ||
} | ||
.scoped-import .bar:before { | ||
content: \\"∑\\"; | ||
} | ||
/* @import util */ | ||
.util { | ||
color: hotpink; | ||
} | ||
/* @import ~module */ | ||
.module { | ||
background: hotpink; | ||
} | ||
/* @import ~another */ | ||
.another-scss-module-from-node-modules { | ||
background: hotpink; | ||
} | ||
a { | ||
color: red; | ||
}" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import sass from 'sass'; | ||
import resolve from 'enhanced-resolve'; | ||
|
||
import createSassImporter from '../src/importer'; | ||
|
||
describe('importer', () => { | ||
it('should resolve imports when passed to `sass`', (done) => { | ||
const importer = createSassImporter(resolve.create); | ||
|
||
sass.render( | ||
{ | ||
file: 'test/sass/imports.sass', | ||
importer, | ||
}, | ||
(err, result) => { | ||
expect(result.css.toString()).toMatchSnapshot(); | ||
|
||
done(err); | ||
} | ||
); | ||
}); | ||
}); |