normalizeOptions.js 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. 'use strict';
  2. const os = require('os');
  3. const path = require('path');
  4. const utils = require('loader-utils');
  5. const cloneDeep = require('clone-deep');
  6. const proxyCustomImporters = require('./proxyCustomImporters');
  7. /**
  8. * Derives the sass options from the loader context and normalizes its values with sane defaults.
  9. *
  10. * Please note: If loaderContext.query is an options object, it will be re-used across multiple invocations.
  11. * That's why we must not modify the object directly.
  12. *
  13. * @param {LoaderContext} loaderContext
  14. * @param {string} content
  15. * @param {Function} webpackImporter
  16. * @returns {Object}
  17. */
  18. function normalizeOptions(loaderContext, content, webpackImporter) {
  19. const options = cloneDeep(utils.getOptions(loaderContext)) || {};
  20. const { resourcePath } = loaderContext;
  21. // allow opt.functions to be configured WRT loaderContext
  22. if (typeof options.functions === 'function') {
  23. options.functions = options.functions(loaderContext);
  24. }
  25. let { data } = options;
  26. if (typeof options.data === 'function') {
  27. data = options.data(loaderContext);
  28. }
  29. options.data = data ? data + os.EOL + content : content;
  30. // opt.outputStyle
  31. if (!options.outputStyle && loaderContext.minimize) {
  32. options.outputStyle = 'compressed';
  33. }
  34. // opt.sourceMap
  35. // Not using the `this.sourceMap` flag because css source maps are different
  36. // @see https://github.com/webpack/css-loader/pull/40
  37. if (options.sourceMap) {
  38. // Deliberately overriding the sourceMap option here.
  39. // node-sass won't produce source maps if the data option is used and options.sourceMap is not a string.
  40. // In case it is a string, options.sourceMap should be a path where the source map is written.
  41. // But since we're using the data option, the source map will not actually be written, but
  42. // all paths in sourceMap.sources will be relative to that path.
  43. // Pretty complicated... :(
  44. options.sourceMap = path.join(process.cwd(), '/sass.map');
  45. if ('sourceMapRoot' in options === false) {
  46. options.sourceMapRoot = process.cwd();
  47. }
  48. if ('omitSourceMapUrl' in options === false) {
  49. // The source map url doesn't make sense because we don't know the output path
  50. // The css-loader will handle that for us
  51. options.omitSourceMapUrl = true;
  52. }
  53. if ('sourceMapContents' in options === false) {
  54. // If sourceMapContents option is not set, set it to true otherwise maps will be empty/null
  55. // when exported by webpack-extract-text-plugin.
  56. options.sourceMapContents = true;
  57. }
  58. }
  59. // indentedSyntax is a boolean flag.
  60. const ext = path.extname(resourcePath);
  61. // If we are compiling sass and indentedSyntax isn't set, automatically set it.
  62. if (
  63. ext &&
  64. ext.toLowerCase() === '.sass' &&
  65. 'indentedSyntax' in options === false
  66. ) {
  67. options.indentedSyntax = true;
  68. } else {
  69. options.indentedSyntax = Boolean(options.indentedSyntax);
  70. }
  71. // Allow passing custom importers to `node-sass`. Accepts `Function` or an array of `Function`s.
  72. options.importer = options.importer
  73. ? proxyCustomImporters(options.importer, resourcePath)
  74. : [];
  75. options.importer.push(webpackImporter);
  76. // `node-sass` uses `includePaths` to resolve `@import` paths. Append the currently processed file.
  77. options.includePaths = options.includePaths || [];
  78. options.includePaths.push(path.dirname(resourcePath));
  79. return options;
  80. }
  81. module.exports = normalizeOptions;