System.register(['reactive-jsx', './lodash-bound.js', './monads.js'], function (_export, _context) {
  "use strict";

  var _addSourceLocation, _childSpread, _childExpression, _childText, _children, _attributeStringLiteral, _attributes, _element, FreeMonad;

  return {
    setters: [function (_reactiveJsx) {
      _addSourceLocation = _reactiveJsx.addSourceLocation;
      _childSpread = _reactiveJsx.childSpread;
      _childExpression = _reactiveJsx.childExpression;
      _childText = _reactiveJsx.childText;
      _children = _reactiveJsx.children;
      _attributeStringLiteral = _reactiveJsx.attributeStringLiteral;
      _attributes = _reactiveJsx.attributes;
      _element = _reactiveJsx.element;
    }, function (_lodashBoundJs) {
      var _exportObj = {};

      for (var _key in _lodashBoundJs) {
        if (_key !== "default" && _key !== "__esModule") _exportObj[_key] = _lodashBoundJs[_key];
      }

      _export(_exportObj);
    }, function (_monadsJs) {
      FreeMonad = _monadsJs.FreeMonad;
    }],
    execute: function () {
      const __SystemJSRewritingHack = {};
      _recorder_._src_client_utils_js = _recorder_._src_client_utils_js || {};
      Object.defineProperty(_recorder_._src_client_utils_js, 'range', {
        get() {
          return range;
        },

        set(thisIsVererySecretVariableName) {
          _export('range', range = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'isRange', {
        get() {
          return isRange;
        },

        set(thisIsVererySecretVariableName) {
          isRange = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'loc', {
        get() {
          return loc;
        },

        set(thisIsVererySecretVariableName) {
          _export('loc', loc = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'cmToBabel', {
        get() {
          return cmToBabel;
        },

        set(thisIsVererySecretVariableName) {
          cmToBabel = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'babelToCM', {
        get() {
          return babelToCM;
        },

        set(thisIsVererySecretVariableName) {
          babelToCM = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'updateEditors', {
        get() {
          return updateEditors;
        },

        set(thisIsVererySecretVariableName) {
          _export('updateEditors', updateEditors = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'shake', {
        get() {
          return shake;
        },

        set(thisIsVererySecretVariableName) {
          _export('shake', shake = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'onStyleChange', {
        get() {
          return onStyleChange;
        },

        set(thisIsVererySecretVariableName) {
          _export('onStyleChange', onStyleChange = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'using', {
        get() {
          return using;
        },

        set(thisIsVererySecretVariableName) {
          _export('using', using = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'wait', {
        get() {
          return wait;
        },

        set(thisIsVererySecretVariableName) {
          _export('wait', wait = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'parseQuery', {
        get() {
          return parseQuery;
        },

        set(thisIsVererySecretVariableName) {
          _export('parseQuery', parseQuery = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'waitForDeepProperty', {
        get() {
          return waitForDeepProperty;
        },

        set(thisIsVererySecretVariableName) {
          _export('waitForDeepProperty', waitForDeepProperty = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'getDeepProperty', {
        get() {
          return getDeepProperty;
        },

        set(thisIsVererySecretVariableName) {
          _export('getDeepProperty', getDeepProperty = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'textualRepresentation', {
        get() {
          return textualRepresentation;
        },

        set(thisIsVererySecretVariableName) {
          _export('textualRepresentation', textualRepresentation = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'cancelEvent', {
        get() {
          return cancelEvent;
        },

        set(thisIsVererySecretVariableName) {
          _export('cancelEvent', cancelEvent = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'isFunction', {
        get() {
          return isFunction;
        },

        set(thisIsVererySecretVariableName) {
          _export('isFunction', isFunction = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'functionMetaInfo', {
        get() {
          return functionMetaInfo;
        },

        set(thisIsVererySecretVariableName) {
          _export('functionMetaInfo', functionMetaInfo = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'copyTextToClipboard', {
        get() {
          return copyTextToClipboard;
        },

        set(thisIsVererySecretVariableName) {
          _export('copyTextToClipboard', copyTextToClipboard = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'uuid', {
        get() {
          return uuid;
        },

        set(thisIsVererySecretVariableName) {
          _export('uuid', uuid = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'removeTempKey', {
        get() {
          return removeTempKey;
        },

        set(thisIsVererySecretVariableName) {
          _export('removeTempKey', removeTempKey = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'getObjectFor', {
        get() {
          return getObjectFor;
        },

        set(thisIsVererySecretVariableName) {
          _export('getObjectFor', getObjectFor = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'getTempKeyFor', {
        get() {
          return getTempKeyFor;
        },

        set(thisIsVererySecretVariableName) {
          _export('getTempKeyFor', getTempKeyFor = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'listAsDragImage', {
        get() {
          return listAsDragImage;
        },

        set(thisIsVererySecretVariableName) {
          _export('listAsDragImage', listAsDragImage = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'asDragImageFor', {
        get() {
          return asDragImageFor;
        },

        set(thisIsVererySecretVariableName) {
          _export('asDragImageFor', asDragImageFor = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'hintForLabel', {
        get() {
          return hintForLabel;
        },

        set(thisIsVererySecretVariableName) {
          _export('hintForLabel', hintForLabel = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'pluralize', {
        get() {
          return pluralize;
        },

        set(thisIsVererySecretVariableName) {
          _export('pluralize', pluralize = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'replaceFileEndingWith', {
        get() {
          return replaceFileEndingWith;
        },

        set(thisIsVererySecretVariableName) {
          _export('replaceFileEndingWith', replaceFileEndingWith = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'fileEnding', {
        get() {
          return fileEnding;
        },

        set(thisIsVererySecretVariableName) {
          _export('fileEnding', fileEnding = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'fileName', {
        get() {
          return fileName;
        },

        set(thisIsVererySecretVariableName) {
          _export('fileName', fileName = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'promisedEvent2', {
        get() {
          return promisedEvent2;
        },

        set(thisIsVererySecretVariableName) {
          _export('promisedEvent2', promisedEvent2 = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'promisedEvent', {
        get() {
          return promisedEvent;
        },

        set(thisIsVererySecretVariableName) {
          _export('promisedEvent', promisedEvent = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'executeAllTestRunners', {
        get() {
          return executeAllTestRunners;
        },

        set(thisIsVererySecretVariableName) {
          _export('executeAllTestRunners', executeAllTestRunners = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_utils_js, 'FreeMonad', {
        get() {
          return FreeMonad;
        },

        set(thisIsVererySecretVariableName) {
          FreeMonad = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function executeAllTestRunners() {
        document.querySelectorAll('lively-testrunner').forEach(runner => runner.onRunButton());
      }

      _export('executeAllTestRunners', executeAllTestRunners);

      function promisedEvent(eventTarget, type) {
        if (!type || !eventTarget) throw new Error("arguments missing");
        return new Promise(resolve => eventTarget.addEventListener(type, resolve));
      }

      _export('promisedEvent', promisedEvent);

      function promisedEvent2(eventTarget, type) {
        if (!type || !eventTarget) throw new Error("arguments missing");
        return new FreeMonad(resolve => eventTarget.addEventListener(type, resolve));
      }

      // #TODO: make this more robust to urlStrings that do not contain a filename, e.g.
      // "https://goole.com"::fileName() should not "goole.com"

      _export('promisedEvent2', promisedEvent2);

      function fileName() {
        return this.replace(/.*\//, "");
      }

      // Example usage: "path/to/a.json"::fileEnding() returns "json"
      // #TODO: make this more robust to strings that do not contain a file ending

      _export('fileName', fileName);

      function fileEnding() {
        return this.replace(/.*\./, "");
      }

      // Example usage: "path/to/a.json"::replaceFileEndingWith("xml") returns "path/to/a.xml"
      // #TODO: make this more robust to strings that do not contain a file ending

      _export('fileEnding', fileEnding);

      function replaceFileEndingWith(newEnding) {
        return this.replace(/[^\.]+$/, newEnding);
      }

      // 2, "egg" -> "2 eggs" | 1, "egg" -> "1 egg" | 2, "life", "lives" -> "2 lives"

      _export('replaceFileEndingWith', replaceFileEndingWith);

      function pluralize(count, name, pluralForm = undefined) {
        if (count == 1) return count + " " + name;
        return count + " " + (pluralForm || name + "s");
      }

      _export('pluralize', pluralize);

      class PausableLoop {
        constructor(func) {
          this.func = func;
          this.cancelID;
          this.running = false;
        }

        ensureRunning() {
          if (!this.running) {
            this.running = true;

            const loopBody = () => {
              this.func();
              if (this.running) {
                this.cancelID = requestAnimationFrame(loopBody);
              }
            };

            this.cancelID = requestAnimationFrame(loopBody);
          }
        }

        pause() {
          cancelAnimationFrame(this.cancelID);
          this.running = false;
        }
      }

      _export('PausableLoop', PausableLoop);

      Object.defineProperty(_recorder_._src_client_utils_js, 'PausableLoop', {
        get() {
          return PausableLoop;
        },

        set(thisIsVererySecretVariableName) {
          _export('PausableLoop', PausableLoop = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      function hintForLabel(label) {
        return _element('div', _attributes(_attributeStringLiteral('style', '\\n    margin: 0.5px 0px;\\n    font-size: x-small;\\n    background-color: lightgray;\\n    border: 1px solid gray;\\n    border-radius: 2px;\\n    max-width: fit-content;\\n    white-space: nowrap;\\n    overflow: hidden;\\n    text-overflow: ellipsis;\\n  ')), _children(_childText('\n    '), _childExpression(label), _childText('\n  ')), {
          file: 'https://lively-kernel.org/lively4/lively4-portal/src/client/utils.js',
          end: {
            column: 8,
            line: 79
          },
          start: {
            column: 9,
            line: 77
          }
        });
      }

      // #TODO: chrome does not support dataTransfer.addElement :(
      // e.g. dt.addElement(<h1>drop me</h1>);
      // Therefore, we have to perform this hack stolen from:
      // https://stackoverflow.com/questions/12766103/html5-drag-and-drop-events-and-setdragimage-browser-support

      _export('hintForLabel', hintForLabel);

      function asDragImageFor(evt, offsetX = 0, offsetY = 0) {
        const clone = this.cloneNode(true);
        document.body.appendChild(clone);
        clone.style["z-index"] = "10000000";
        clone.style.top = Math.max(0, evt.clientY - offsetY) + "px";
        clone.style.left = Math.max(0, evt.clientX - offsetX) + "px";
        clone.style.position = "absolute";
        clone.style.pointerEvents = "none";

        setTimeout(clone.remove.bind(clone));
        evt.dataTransfer.setDragImage(clone, offsetX, offsetY);
      }

      _export('asDragImageFor', asDragImageFor);

      function listAsDragImage(labels, evt, offsetX, offsetY) {
        const hints = labels.map(textualRepresentation).map(hintForLabel);
        const hintLength = hints.length;
        const maxLength = 5;
        if (hints.length > maxLength) {
          hints.length = maxLength;
          hints.push(hintForLabel(`+ ${hintLength - maxLength} more.`));
        }
        const dragInfo = _element('div', _attributes(_attributeStringLiteral('style', 'width: 151px;')), _children(_childText('\n    '), _childSpread(hints), _childText('\n  ')), {
          file: 'https://lively-kernel.org/lively4/lively4-portal/src/client/utils.js',
          end: {
            column: 8,
            line: 109
          },
          start: {
            column: 19,
            line: 107
          }
        });
        asDragImageFor.call(dragInfo, evt, offsetX, offsetY);
      }

      _export('listAsDragImage', listAsDragImage);

      const TEMP_OBJECT_STORAGE = new Map();
      Object.defineProperty(_recorder_._src_client_utils_js, 'TEMP_OBJECT_STORAGE', {
        get() {
          return TEMP_OBJECT_STORAGE;
        },

        set(thisIsVererySecretVariableName) {
          TEMP_OBJECT_STORAGE = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function getTempKeyFor(obj) {
        const tempKey = uuid();
        TEMP_OBJECT_STORAGE.set(tempKey, obj);

        // safety net: remove the key in 10 minutes
        setTimeout(() => removeTempKey(tempKey), 10 * 60 * 1000);

        return tempKey;
      }

      _export('getTempKeyFor', getTempKeyFor);

      function getObjectFor(tempKey) {
        return TEMP_OBJECT_STORAGE.get(tempKey);
      }

      _export('getObjectFor', getObjectFor);

      function removeTempKey(tempKey) {
        TEMP_OBJECT_STORAGE.delete(tempKey);
      }

      _export('removeTempKey', removeTempKey);

      function uuid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
          var r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0,
              v = c == 'x' ? r : r & 0x3 | 0x8;
          return v.toString(16);
        });
      }

      /**
       * Taken from and modified using:
       * https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
       */

      _export('uuid', uuid);

      function copyTextToClipboard(text) {
        const textArea = _addSourceLocation(document.createElement("textarea"), {
          file: 'https://lively-kernel.org/lively4/lively4-portal/src/client/utils.js',
          end: {
            column: 53,
            line: 143
          },
          start: {
            column: 19,
            line: 143
          }
        });

        //
        // *** This styling is an extra step which is likely not required. ***
        //
        // Why is it here? To ensure:
        // 1. the element is able to have focus and selection.
        // 2. if element was to flash render it has minimal visual impact.
        // 3. less flakyness with selection and copying which **might** occur if
        //    the textarea element is not visible.
        //
        // The likelihood is the element won't even render, not even a flash,
        // so some of these are just precautions. However in IE the element
        // is visible whilst the popup box asking the user for permission for
        // the web page to copy to the clipboard.
        //

        Object.assign(textArea.style, {
          // Place in top-left corner of screen regardless of scroll position.
          position: 'fixed',
          top: 0,
          left: 0,

          // Ensure it has a small width and height. Setting to 1px / 1em
          // doesn't work as this gives a negative w/h on some browsers.
          width: '2em',
          height: '2em',

          // We don't need padding, reducing the size if it does flash render.
          padding: 0,

          // Clean up any borders.
          border: 'none',
          outline: 'none',
          boxShadow: 'none',

          // Avoid flash of white box if rendered for any reason.
          background: 'transparent'
        });

        textArea.value = text;

        document.body.appendChild(textArea);

        textArea.select();

        let supported;
        try {
          supported = document.queryCommandSupported('copy');
        } catch (err) {
          lively.warn('Copy to clipboard not supported.', err);
          supported = false;
        }
        if (supported) {
          let enabled;
          try {
            enabled = document.queryCommandEnabled('copy');
          } catch (err) {
            lively.warn('Copy to clipboard not enabled.', err);
            enabled = false;
          }
          if (enabled) {
            try {
              if (!document.execCommand('copy')) {
                lively.warn('Copying not successful.');
              }
            } catch (err) {
              lively.warn('Unable to execute copy.');
            }
          }
        }

        document.body.removeChild(textArea);
      }

      _export('copyTextToClipboard', copyTextToClipboard);

      function functionMetaInfo(functionToCheck) {
        if (functionToCheck === undefined) {
          return {
            isFunction: false,
            isAsync: false,
            isGenerator: false
          };
        }

        const description = {}.toString.call(functionToCheck);
        return {
          isFunction: !!description.match(/\[object (Async)?(Generator)?Function\]/),
          isAsync: !!description.match(/\[object Async(Generator)?Function\]/),
          isGenerator: !!description.match(/\[object (Async)?GeneratorFunction\]/)
        };
      }
      // taken from https://stackoverflow.com/questions/5999998/how-can-i-check-if-a-javascript-variable-is-function-type

      _export('functionMetaInfo', functionMetaInfo);

      function isFunction(functionToCheck) {
        if (functionToCheck === undefined) {
          return false;
        }
        let isFunc = {}.toString.call(functionToCheck) === '[object Function]';
        let isAsyncFunc = {}.toString.call(functionToCheck) === '[object AsyncFunction]';
        return isFunc || isAsyncFunc;
      }

      _export('isFunction', isFunction);

      function cancelEvent(evt) {
        evt.stopPropagation();
        evt.preventDefault();
      }

      _export('cancelEvent', cancelEvent);

      function textualRepresentation(thing) {
        // primitive falsy value?
        if (!thing) {
          return '' + thing;
        }

        // toString method different from Object?
        if (thing.toString && thing.toString !== Object.prototype.toString) {
          return thing.toString();
        }

        // instance of a named class?
        if (thing.constructor && thing.constructor.name) {
          return 'a ' + thing.constructor.name;
        }

        return 'unprintable object';
      }

      _export('textualRepresentation', textualRepresentation);

      function getDeepProperty(obj, pathString) {
        var path = pathString.split(".");
        var next;
        var result = obj;
        while (next = path.shift()) {
          var nextResult = result[next];
          if (!nextResult) return; // could not resolve path
          result = nextResult;
        }
        return result;
      }

      /*
       * waits for the deep construction of a data structure // object
       * 
       */

      _export('getDeepProperty', getDeepProperty);

      async function waitForDeepProperty(obj, pathString, timeout = 60000 /* one minuete */, step = 10) {
        var path = pathString.split(".");
        var next;
        var result = obj;
        var nextResult;
        while (next = path.shift()) {
          nextResult = result[next];
          while (!nextResult) {
            await wait(step // busy waiting...
            );nextResult = result[next];
          }
          // if (!nextResult) return // could not resolve path
          result = nextResult;
          // console.log("next result " + next + " = " + result )
        }
        return result;
      }

      // https://stackoverflow.com/questions/2090551/parse-query-string-in-javascript

      _export('waitForDeepProperty', waitForDeepProperty);

      function parseQuery(queryString) {
        var query = {};
        var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
        for (var i = 0; i < pairs.length; i++) {
          var pair = pairs[i].split('=');
          query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
        }
        return query;
      }

      _export('parseQuery', parseQuery);

      function wait(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
      }

      _export('wait', wait);

      class CallableObject {}
      // #TODO: implement this


      /**
       * Executes the given function considering the given context objects.
       * @param {Array<ContextManager>} contexts
       * @param {function} callback
       * @return {Object} result - The callback's evaluation result.
       *
       * @class ContextManager
       * @classdesc Used to specify the setup and teardown of the function call.
       * @method {__enter__} enter callback - called before the function call. Put setup code here.
       * @method {__exit__} exit callback - called after the funciton call. Put teardown code here.
      
       * @example <caption>Poor mans COP.</caption>
       * import { using }from "utils";
       * 
       * const silentFetch = {
       *   __enter__() {
       *     this.originalFetch = window.fetch;
       *     window.fetch = () => {};
       *   }
       *   __exit__() {
       *     window.fetch = this.originalFetch; // restore the original fetch 
       *   }
       * }
       *
       * using([silentFetch], () => {
       *   lively.notify(fetch('https://lively-kernel.org/lively4/')) // logs nothing
       * });
       */

      _export('CallableObject', CallableObject);

      Object.defineProperty(_recorder_._src_client_utils_js, 'CallableObject', {
        get() {
          return CallableObject;
        },

        set(thisIsVererySecretVariableName) {
          _export('CallableObject', CallableObject = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      function using(contextManagerIterable, callback) {
        let result;
        let error;
        const contextManagers = Array.from(contextManagerIterable);

        contextManagers.forEach(cm => cm.__enter__());
        try {
          result = callback();
        } catch (e) {
          error = e;
        } finally {
          contextManagers.reverse().forEach(cm => cm.__exit__(error));
        }
        if (error !== undefined) {
          throw error;
        }
        return result;
      }

      /**
       * Get notified, whenever the style attribute of given target changes
       */

      _export('using', using);

      function onStyleChange(target, callback) {
        const styleObserver = new MutationObserver(mutations => {
          mutations.forEach(mutation => {
            if (mutation.type == "attributes" && mutation.attributeName == "style") {
              callback();
            }
          });
        });
        styleObserver.observe(target, { attributes: true });

        return styleObserver;
      }

      /**
       * shakes given element using css transformations
       */

      _export('onStyleChange', onStyleChange);

      function shake(target) {
        target.animate([{ transform: 'translate(1px, 1px) rotate(0deg)' }, { transform: 'translate(-1px, -2px) rotate(-1deg)' }, { transform: 'translate(-3px, 0px) rotate(1deg)' }, { transform: 'translate(3px, 2px) rotate(0deg)' }, { transform: 'translate(1px, -1px) rotate(1deg)' }, { transform: 'translate(-1px, 2px) rotate(-1deg)' }, { transform: 'translate(-3px, 1px) rotate(0deg)' }, { transform: 'translate(3px, 1px) rotate(-1deg)' }, { transform: 'translate(-1px, -1px) rotate(1deg)' }, { transform: 'translate(1px, 2px) rotate(0deg)' }, { transform: 'translate(1px, -2px) rotate(-1deg)' }], {
          // timing options
          duration: 100,
          iterations: 1
          // easing: 'cubic-bezier(0.42, 0, 0.58, 1)'
        });
      }

      _export('shake', shake);

      function updateEditors(url, excludedEditors = []) {

        url = url.toString().replace(/[#?].*/, "");

        const editors = lively.findAllElements(ea => ea.localName == "lively-editor", true);
        const editorsToUpdate = editors.filter(ea => ea.getURLString().replace(/[#?].*/, "") === url && !ea.textChanged && !excludedEditors.includes(ea));

        editorsToUpdate.forEach(ea => {
          var codeMirror = ea.get("lively-code-mirror");
          var scrollInfo = codeMirror.editor.getScrollInfo();
          ea.loadFile
          // preserve scroll position during updating
          ();codeMirror.editor.scrollTo(null, scrollInfo.top);
        });
      }

      /*MD Source Code Locations and Ranges MD*/

      _export('updateEditors', updateEditors);

      function babelToCM(babelPosition) {
        return {
          line: babelPosition.line - 1,
          ch: babelPosition.column
        };
      }

      function cmToBabel(cmPosition) {
        return {
          line: cmPosition.line + 1,
          column: cmPosition.ch
        };
      }

      class Location {
        get isLocation() {
          return true;
        }

        constructor(l) {
          this._cmLine = l.line;
          this._cmCharacter = l.ch;
        }

        isEqual(l) {
          const other = loc(l);
          return this._cmLine === other._cmLine && this._cmCharacter === other._cmCharacter;
        }
        isBefore(l) {
          const other = loc(l);
          return this._cmLine < other._cmLine || this._cmLine === other._cmLine && this._cmCharacter <= other._cmCharacter;
        }
        isStrictBefore(l) {
          const other = loc(l);
          return this._cmLine < other._cmLine || this._cmLine === other._cmLine && this._cmCharacter < other._cmCharacter;
        }

        asBabel() {
          return cmToBabel(this.asCM());
        }
        asCM() {
          return {
            line: this._cmLine,
            ch: this._cmCharacter
          };
        }

        innerToString() {
          return `${this._cmLine}:${this._cmCharacter}`;
        }
        toString() {
          return `loc(${this.innerToString()})`;
        }
      }

      Object.defineProperty(_recorder_._src_client_utils_js, 'Location', {
        get() {
          return Location;
        },

        set(thisIsVererySecretVariableName) {
          Location = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function loc(l) {
        if (l.isLocation) {
          return l;
        }
        // cm style
        if (l.ch !== undefined) {
          return new Location(l);
        }
        // babel style
        if (l.column !== undefined) {
          return new Location(babelToCM(l));
        }
        throw new Error(`Location value ${l} not recognized.`);
      }

      _export('loc', loc);

      class Range {
        get isRange() {
          return true;
        }

        constructor(start, end) {
          this.setRange(start, end);
        }

        setRange(start, end) {
          if (loc(end).isStrictBefore(loc(start))) {
            this.setRange(end, start);
            return;
          }
          this.start = loc(start);
          this.end = loc(end);
        }

        asBabel() {
          throw new Error('asBabel not yet implemented.');
        }

        asCM() {
          // from, to
          return [this.start.asCM(), this.end.asCM()];
        }

        contains(location) {
          if (isRange(location)) {
            return this.containsRange(range(location));
          }
          const ll = loc(location);
          return this.start.isBefore(ll) && ll.isBefore(this.end);
        }

        strictlyContains(location) {
          if (location.isRange) {
            return strictlyContainsRange(location);
          }
          const ll = loc(location);
          return this.start.isStrictBefore(ll) && ll.isStrictBefore(this.end);
        }

        containsRange(range) {
          return this.contains(range.start) && this.contains(range.end);
        }

        strictlyContainsRange(range) {
          if (range.start.isEqual(range.end)) return this.containsRange(range);
          return this.strictlyContains(range.start) || this.strictlyContains(range.end);
        }

        containsPartsOfRange(range) {
          return this.contains(range.start) || this.contains(range.end);
        }

        isEqual(range) {
          return this.start.isEqual(range.start) && this.end.isEqual(range.end);
        }

        isBehind(l) {
          return loc(l).isBefore(this.start);
        }

        isBefore(l) {
          return this.end.isBefore(loc(l));
        }

        selectInCM(cm) {
          cm.setSelection(...this.asCM());
        }

        toString() {
          return `range(${this.start.innerToString()}, ${this.end.innerToString()})`;
        }
      }

      Object.defineProperty(_recorder_._src_client_utils_js, 'Range', {
        get() {
          return Range;
        },

        set(thisIsVererySecretVariableName) {
          Range = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function isRange(r) {
        if (r.isRange) {
          return true;
        }
        // cm style
        if (Array.isArray(r)) {
          return true;
        }
        if (r.anchor && r.head) {
          return true;
        }
        // babel style
        if (r.start && r.end) {
          return true;
        }
        return false;
      }

      function range(r) {
        if (r.isRange) {
          return r;
        }
        // cm style
        if (Array.isArray(r)) {
          return new Range(r.first, r.second);
        }
        if (r.anchor && r.head) {
          return new Range(r.anchor, r.head);
        }
        // babel style
        if (r.start && r.end) {
          return new Range(r.start, r.end);
        }
        throw new Error(`Range value ${r} not recognized.`);
      }

      _export('range', range);
    }
  };
});