loader.js 2.5 KB

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