loader.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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 { getMatchedRules, getLoadersRules, 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, resource, 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 issuer = loaderContext._module && loaderContext._module.issuer;
  23. const matchedRules = getMatchedRules(resource, getLoadersRules(compiler), issuer);
  24. if (!content.includes('<svg')) {
  25. throw new Exceptions.InvalidSvg(content, matchedRules);
  26. }
  27. const configObj = { context: loaderContext };
  28. if (getWebpackVersion.IS_4) {
  29. configObj.config = loaderContext.query;
  30. configObj.target = loaderContext.target;
  31. } else {
  32. configObj.config = getOptions(loaderContext);
  33. configObj.target = loaderContext.options.target || loaderContext.target;
  34. }
  35. /**
  36. * @type {SVGSpriteLoaderConfig}
  37. */
  38. const config = configure(configObj);
  39. if (config.extract) {
  40. const plugin = parentCompiler
  41. ? parentCompiler.options.plugins.find(p => p.NAMESPACE && p.NAMESPACE === NAMESPACE)
  42. : this[NAMESPACE];
  43. if (typeof plugin === 'undefined') {
  44. throw new Exceptions.ExtractPluginMissingException();
  45. }
  46. if (loaderIndex > 0) {
  47. this.emitWarning(new Exceptions.RemainingLoadersInExtractModeException());
  48. }
  49. svgCompiler = plugin.svgCompiler;
  50. }
  51. let runtimeGenerator;
  52. try {
  53. runtimeGenerator = require(config.runtimeGenerator); // eslint-disable-line import/no-dynamic-require,global-require
  54. } catch (e) {
  55. throw new Exceptions.InvalidRuntimeException(e.message);
  56. }
  57. const idPattern = config.symbolId + (resourceQuery ? `--${urlSlug(resourceQuery)}` : '');
  58. const id = interpolateName(loaderContext, idPattern, {
  59. content,
  60. context: compiler.context,
  61. regExp: config.symbolRegExp
  62. });
  63. svgCompiler.addSymbol({ id, content, path: resourcePath + resourceQuery })
  64. .then((symbol) => {
  65. const runtime = runtimeGenerator({ symbol, config, context: rootContext, loaderContext });
  66. done(null, runtime);
  67. }).catch(done);
  68. };
  69. module.exports.NAMESPACE = NAMESPACE;