loader.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. const { interpolateName, getOptions } = require('loader-utils');
  2. const urlSlug = require('url-slug');
  3. const SVGCompiler = require('svg-baker');
  4. const { NAMESPACE } = require('./config');
  5. const configure = require('./configurator');
  6. const { getWebpackVersion } = require('./utils');
  7. const Exceptions = require('./exceptions');
  8. let svgCompiler = new SVGCompiler();
  9. // eslint-disable-next-line consistent-return
  10. module.exports = function loader(content) {
  11. if (this.cacheable) {
  12. this.cacheable();
  13. }
  14. const done = this.async();
  15. const loaderContext = this;
  16. const { resourcePath, rootContext, loaderIndex } = loaderContext;
  17. // webpack 1 compat
  18. const resourceQuery = loaderContext.resourceQuery || '';
  19. const compiler = loaderContext._compiler;
  20. const isChildCompiler = compiler.isChild();
  21. const parentCompiler = isChildCompiler ? compiler.parentCompilation.compiler : null;
  22. const matchedRules = getOptions(loaderContext);
  23. if (!content.includes('<svg')) {
  24. throw new Exceptions.InvalidSvg(content, matchedRules);
  25. }
  26. const configObj = { context: loaderContext };
  27. if (getWebpackVersion.IS_4) {
  28. configObj.config = loaderContext.query;
  29. configObj.target = loaderContext.target;
  30. } else {
  31. configObj.config = matchedRules;
  32. configObj.target = loaderContext.options.target || loaderContext.target;
  33. }
  34. /**
  35. * @type {SVGSpriteLoaderConfig}
  36. */
  37. const config = configure(configObj);
  38. if (config.extract) {
  39. const plugin = parentCompiler
  40. ? parentCompiler.options.plugins.find(p => p.NAMESPACE && p.NAMESPACE === NAMESPACE)
  41. : this[NAMESPACE];
  42. if (typeof plugin === 'undefined') {
  43. throw new Exceptions.ExtractPluginMissingException();
  44. }
  45. if (loaderIndex > 0) {
  46. this.emitWarning(new Exceptions.RemainingLoadersInExtractModeException());
  47. }
  48. svgCompiler = plugin.svgCompiler;
  49. }
  50. let runtimeGenerator;
  51. try {
  52. runtimeGenerator = require(config.runtimeGenerator); // eslint-disable-line import/no-dynamic-require,global-require
  53. } catch (e) {
  54. throw new Exceptions.InvalidRuntimeException(e.message);
  55. }
  56. let id;
  57. if (typeof config.symbolId === 'function') {
  58. id = config.symbolId(resourcePath, resourceQuery);
  59. } else {
  60. const idPattern = config.symbolId + (resourceQuery ? `--${urlSlug(resourceQuery)}` : '');
  61. id = interpolateName(loaderContext, idPattern, {
  62. content,
  63. context: compiler.context,
  64. regExp: config.symbolRegExp
  65. });
  66. }
  67. svgCompiler.addSymbol({ id, content, path: resourcePath + resourceQuery })
  68. .then((symbol) => {
  69. const runtime = runtimeGenerator({ symbol, config, context: rootContext, loaderContext });
  70. done(null, runtime);
  71. }).catch(done);
  72. };
  73. module.exports.NAMESPACE = NAMESPACE;