Plugin.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. const ChainedMap = require('./ChainedMap');
  2. const Orderable = require('./Orderable');
  3. module.exports = Orderable(
  4. class extends ChainedMap {
  5. constructor(parent, name) {
  6. super(parent);
  7. this.name = name;
  8. this.extend(['init']);
  9. this.init((Plugin, args = []) => {
  10. if (typeof Plugin === 'function') {
  11. return new Plugin(...args);
  12. }
  13. return Plugin;
  14. });
  15. }
  16. use(plugin, args = []) {
  17. return this.set('plugin', plugin).set('args', args);
  18. }
  19. tap(f) {
  20. this.set('args', f(this.get('args') || []));
  21. return this;
  22. }
  23. merge(obj, omit = []) {
  24. if ('plugin' in obj) {
  25. this.set('plugin', obj.plugin);
  26. }
  27. if ('args' in obj) {
  28. this.set('args', obj.args);
  29. }
  30. return super.merge(obj, [...omit, 'args', 'plugin']);
  31. }
  32. toConfig() {
  33. const init = this.get('init');
  34. let plugin = this.get('plugin');
  35. const args = this.get('args');
  36. let pluginPath = null;
  37. // Support using the path to a plugin rather than the plugin itself,
  38. // allowing expensive require()s to be skipped in cases where the plugin
  39. // or webpack configuration won't end up being used.
  40. if (typeof plugin === 'string') {
  41. pluginPath = plugin;
  42. // eslint-disable-next-line global-require, import/no-dynamic-require
  43. plugin = require(pluginPath);
  44. }
  45. const constructorName = plugin.__expression
  46. ? `(${plugin.__expression})`
  47. : plugin.name;
  48. const config = init(plugin, args);
  49. Object.defineProperties(config, {
  50. __pluginName: { value: this.name },
  51. __pluginArgs: { value: args },
  52. __pluginConstructorName: { value: constructorName },
  53. __pluginPath: { value: pluginPath },
  54. });
  55. return config;
  56. }
  57. }
  58. );