webpackImporter.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. "use strict";
  2. /**
  3. * @name PromisedResolve
  4. * @type {Function}
  5. * @param {string} dir
  6. * @param {string} request
  7. * @returns Promise
  8. */
  9. /**
  10. * @name Importer
  11. * @type {Function}
  12. * @param {string} url
  13. * @param {string} prev
  14. * @param {Function<Error, string>} done
  15. */
  16. const path = require("path");
  17. const tail = require("lodash.tail");
  18. const importsToResolve = require("./importsToResolve");
  19. const matchCss = /\.css$/;
  20. /**
  21. * Returns an importer that uses webpack's resolving algorithm.
  22. *
  23. * It's important that the returned function has the correct number of arguments
  24. * (based on whether the call is sync or async) because otherwise node-sass doesn't exit.
  25. *
  26. * @param {string} resourcePath
  27. * @param {PromisedResolve} resolve
  28. * @param {Function<string>} addNormalizedDependency
  29. * @returns {Importer}
  30. */
  31. function webpackImporter(resourcePath, resolve, addNormalizedDependency) {
  32. function dirContextFrom(fileContext) {
  33. return path.dirname(
  34. // The first file is 'stdin' when we're using the data option
  35. fileContext === "stdin" ? resourcePath : fileContext
  36. );
  37. }
  38. function startResolving(dir, importsToResolve) {
  39. return importsToResolve.length === 0 ?
  40. Promise.reject() :
  41. resolve(dir, importsToResolve[0])
  42. .then(resolvedFile => {
  43. // Add the resolvedFilename as dependency. Although we're also using stats.includedFiles, this might come
  44. // in handy when an error occurs. In this case, we don't get stats.includedFiles from node-sass.
  45. addNormalizedDependency(resolvedFile);
  46. return {
  47. // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
  48. file: resolvedFile.replace(matchCss, "")
  49. };
  50. }, () => startResolving(
  51. dir,
  52. tail(importsToResolve)
  53. ));
  54. }
  55. return (url, prev, done) => {
  56. startResolving(
  57. dirContextFrom(prev),
  58. importsToResolve(url)
  59. ) // Catch all resolving errors, return the original file and pass responsibility back to other custom importers
  60. .catch(() => ({ file: url }))
  61. .then(done);
  62. };
  63. }
  64. module.exports = webpackImporter;