function addCodeEditor(container, options, vsEditorPath) {
  return new Promise((resolve, reject) => {
    if (!vsEditorPath) {
      const vsEditorPaths = [
        // monaco-editor is a devDependency of @blockly/dev-tools, look for it
        // there first, otherwise attempt to find it in the local node_modules
        // and finally resort to an online version.
        '../node_modules/@blockly/dev-tools/node_modules/monaco-editor/min/vs',
        '../node_modules/monaco-editor/min/vs',
        'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.19.2/min/vs',
      ];
      // Find the VS loader.
      for (let i = 0; i < vsEditorPaths.length; i++) {
        if (checkFileExists(`${vsEditorPaths[i]}/loader.js`)) {
          vsEditorPath = vsEditorPaths[i];
          break;
        }
      }
    }

    const onLoad = () => {
      const amdRequire = /** @type {?} */ (window.require);
      amdRequire.config({
        paths: {vs: vsEditorPath},
      });

      // Load the monaco editor.
      amdRequire(['vs/editor/editor.main'], () => {
        resolve(createEditor(container, options));
      });
    };

    if (!window.require) {
      const script = document.createElement('script');
      script.type = 'text/javascript';
      script.setAttribute('src', `${vsEditorPath}/loader.js`);
      script.addEventListener('load', onLoad);
      document.body.appendChild(script);
    } else {
      onLoad();
    }
  });
}
Load the monaco editor.
@param {!HTMLElement} container The container element.
@param {Object} options Monaco editor options.
@param {string=} vsEditorPath Optional VS editor path.
@returns {Promise} A promise that resolves with the editor.