Manual Reference Source Test

src/loaders/PluginLoader.js

/**
*  @file ScriptLoader.js
*  @author Liqueur de Toile <contact@liqueurdetoile.com>
*  @licence AGPL-3.0 {@link https://github.com/liqueurdetoile/beloader/blob/master/LICENSE}
*/

import AbstractLoader from 'core/AbstractLoader';

/**
*  Loads a beloader plugin
*
*  @version 1.0.0
*  @since 1.0.0
*  @author Liqueur de Toile <contact@liqueurdetoile.com>
*  @extends {AbstractLoader}
*/
export default class PluginLoader extends AbstractLoader {
  /**
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @param {QueueItem} parent Calling QueueItem
  *  @param {DotObjectArray} options Options for the loader
  *  @param {string} options.name Plugin var name
  *  @param {string} [options.url] Plugin script url
  *  @param {boolean} [options.inline=false]  If `true`,
  *  the plugin script will be evaluated inline
  *  @throw {TypeError} If plugin name is missing
  */
  constructor(parent, options) {
    if (!options.has('name')) throw new TypeError('Beloader : Plugin must have a name');
    if (!options.has('url')) {
      options.data.url = 'https://cdn.jsdelivr.net/gh/beloader/beloader-' + options.data.name + '@latest';
    }
    options.define('inline', false);
    super(parent, options);

    /**
    *  Underlying node for insertion
    *  @type {HTMLElement}
    */
    this._node = undefined;
  }

  /**
  *  Getter that generates HTMLElement to contain script (sync or async)
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *  @type {HTMLElement} HTMLElement <script></script>
  */
  get node() {
    if (typeof this._node === 'undefined') {
      this._node = document.createElement('script');
      this._node.setAttribute('type', 'text/javascript');
      if (!this.options.data.async) {
        this._node.setAttribute('src', this.options.data.url);
      }
    }
    return this._node;
  }

  /**
  *  Insert plugin code in <script> tag with src for sync loading
  *  and import in plugins when finished
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @returns {Promise} Loading promise
  */
  sync() {
    document.querySelector('head').appendChild(this.node);
    return this._loadPlugin(super.sync());

  }

  /**
  *  Load plugin script, insert response in a <script> tag
  *  and import in plugins when finished
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @returns {Promise} Loading promise
  */
  async() {
    if (this.options.data.inline) return this._loadPlugin(super.async());
    this.options.data.async = false;
    this.node.setAttribute('async', '');
    document.querySelector('head').appendChild(this.node);
    return this._loadPlugin(super.sync());
  }

  /**
  *  Description for _load
  *
  *  @version 1.0.0
  *  @since 1.0.0
  *  @author Liqueur de Toile <contact@liqueurdetoile.com>
  *
  *  @param {$type} p Description for p
  *  @returns {type} Return description
  */
  _loadPlugin(p) {
    const _this = this;

    return new Promise((resolve, reject) => {
      p.then((response) => {
        let beloader = _this.parent.parent;

        if (response && _this.options.data.inline) {
          _this.node.innerHTML = response;
          document.querySelector('head').appendChild(_this.node);
        }

        try {
          let plugin = beloader.pluginize(_this.options.data.name, window[_this.options.data.name], _this.options);

          if (plugin.promise) {
            plugin.promise.then(
              () => resolve(),
              (e) => reject('Unable to load plugin : ' + _this.options.name + ' [' + e + ']')
            );
          } else resolve();
        } catch (e) {
          reject('Unable to load plugin : ' + _this.options.name + ' [' + e + ']');
        }
      });
    });
  }
}

export {PluginLoader};