From f5a78c88f85f68236cfe23cc020e3666e01011e0 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 7 May 2020 17:41:10 +0200 Subject: [PATCH] Bump supervisor panel (#1702) --- home-assistant-polymer | 2 +- .../api/panel/7e78115f8d410990252b.worker.js | 3743 ++ .../panel/7e78115f8d410990252b.worker.js.gz | Bin 0 -> 22678 bytes .../api/panel/chunk.066811ee56df2879fa62.js | 14894 +++++ .../panel/chunk.066811ee56df2879fa62.js.gz | Bin 0 -> 104551 bytes .../api/panel/chunk.212065a6c485fbc07bb8.js | 52699 ++++++++++++++++ .../panel/chunk.212065a6c485fbc07bb8.js.gz | Bin 0 -> 419373 bytes .../api/panel/chunk.2fc4abe2797d5b225522.js | 2242 + .../panel/chunk.2fc4abe2797d5b225522.js.gz | Bin 0 -> 21646 bytes .../api/panel/chunk.471576619b80be2a9a29.js | 10010 +++ .../panel/chunk.471576619b80be2a9a29.js.gz | Bin 0 -> 95059 bytes .../api/panel/chunk.58ad269f3d046fed31b8.js | 27 + .../panel/chunk.58ad269f3d046fed31b8.js.gz | Bin 0 -> 864 bytes .../api/panel/chunk.5fc6b1b0b3ba0b00dc02.js | 1160 + .../panel/chunk.5fc6b1b0b3ba0b00dc02.js.gz | Bin 0 -> 13625 bytes .../api/panel/chunk.7e4e863699408dc5d3f5.js | 1089 + .../panel/chunk.7e4e863699408dc5d3f5.js.gz | Bin 0 -> 15808 bytes .../api/panel/chunk.8fce7a70d26a42912747.js | 254 + .../panel/chunk.8fce7a70d26a42912747.js.gz | Bin 0 -> 5712 bytes .../api/panel/chunk.9487f86e4dfa94842721.js | 9348 +++ .../panel/chunk.9487f86e4dfa94842721.js.gz | Bin 0 -> 61477 bytes .../api/panel/chunk.a155352518b31c5b28c4.js | 35 + .../panel/chunk.a155352518b31c5b28c4.js.gz | Bin 0 -> 509 bytes .../api/panel/chunk.aa2617a1b92d3c2ceba8.js | 4996 ++ .../panel/chunk.aa2617a1b92d3c2ceba8.js.gz | Bin 0 -> 41475 bytes .../api/panel/chunk.d08180c2ee3183a149f4.js | 1289 + .../panel/chunk.d08180c2ee3183a149f4.js.gz | Bin 0 -> 14468 bytes supervisor/api/panel/entrypoint.js | 227 +- supervisor/api/panel/entrypoint.js.gz | Bin 1613 -> 2848 bytes supervisor/api/panel/manifest.json | 53 +- 30 files changed, 102025 insertions(+), 43 deletions(-) create mode 100644 supervisor/api/panel/7e78115f8d410990252b.worker.js create mode 100644 supervisor/api/panel/7e78115f8d410990252b.worker.js.gz create mode 100644 supervisor/api/panel/chunk.066811ee56df2879fa62.js create mode 100644 supervisor/api/panel/chunk.066811ee56df2879fa62.js.gz create mode 100644 supervisor/api/panel/chunk.212065a6c485fbc07bb8.js create mode 100644 supervisor/api/panel/chunk.212065a6c485fbc07bb8.js.gz create mode 100644 supervisor/api/panel/chunk.2fc4abe2797d5b225522.js create mode 100644 supervisor/api/panel/chunk.2fc4abe2797d5b225522.js.gz create mode 100644 supervisor/api/panel/chunk.471576619b80be2a9a29.js create mode 100644 supervisor/api/panel/chunk.471576619b80be2a9a29.js.gz create mode 100644 supervisor/api/panel/chunk.58ad269f3d046fed31b8.js create mode 100644 supervisor/api/panel/chunk.58ad269f3d046fed31b8.js.gz create mode 100644 supervisor/api/panel/chunk.5fc6b1b0b3ba0b00dc02.js create mode 100644 supervisor/api/panel/chunk.5fc6b1b0b3ba0b00dc02.js.gz create mode 100644 supervisor/api/panel/chunk.7e4e863699408dc5d3f5.js create mode 100644 supervisor/api/panel/chunk.7e4e863699408dc5d3f5.js.gz create mode 100644 supervisor/api/panel/chunk.8fce7a70d26a42912747.js create mode 100644 supervisor/api/panel/chunk.8fce7a70d26a42912747.js.gz create mode 100644 supervisor/api/panel/chunk.9487f86e4dfa94842721.js create mode 100644 supervisor/api/panel/chunk.9487f86e4dfa94842721.js.gz create mode 100644 supervisor/api/panel/chunk.a155352518b31c5b28c4.js create mode 100644 supervisor/api/panel/chunk.a155352518b31c5b28c4.js.gz create mode 100644 supervisor/api/panel/chunk.aa2617a1b92d3c2ceba8.js create mode 100644 supervisor/api/panel/chunk.aa2617a1b92d3c2ceba8.js.gz create mode 100644 supervisor/api/panel/chunk.d08180c2ee3183a149f4.js create mode 100644 supervisor/api/panel/chunk.d08180c2ee3183a149f4.js.gz diff --git a/home-assistant-polymer b/home-assistant-polymer index 5ca63a805..ca1cc7ed0 160000 --- a/home-assistant-polymer +++ b/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 5ca63a80522a867557de20fe7bda0592e8f06e7e +Subproject commit ca1cc7ed0dd49efbf1cd510474f028b7b8db313f diff --git a/supervisor/api/panel/7e78115f8d410990252b.worker.js b/supervisor/api/panel/7e78115f8d410990252b.worker.js new file mode 100644 index 000000000..25fc87dba --- /dev/null +++ b/supervisor/api/panel/7e78115f8d410990252b.worker.js @@ -0,0 +1,3743 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/api/hassio/app/"; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 8); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * cssfilter + * + * @author 老雷 + */ +var DEFAULT = __webpack_require__(4); + +var FilterCSS = __webpack_require__(10); +/** + * XSS过滤 + * + * @param {String} css 要过滤的CSS代码 + * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr + * @return {String} + */ + + +function filterCSS(html, options) { + var xss = new FilterCSS(options); + return xss.process(html); +} // 输出 + + +exports = module.exports = filterCSS; +exports.FilterCSS = FilterCSS; + +for (var i in DEFAULT) { + exports[i] = DEFAULT[i]; +} // 在浏览器端使用 + + +if (typeof window !== 'undefined') { + window.filterCSS = module.exports; +} + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + +module.exports = { + indexOf: function indexOf(arr, item) { + var i, j; + + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + + return -1; + }, + forEach: function forEach(arr, fn, scope) { + var i, j; + + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function trim(str) { + if (String.prototype.trim) { + return str.trim(); + } + + return str.replace(/(^\s*)|(\s*$)/g, ""); + }, + spaceIndex: function spaceIndex(str) { + var reg = /\s|\n|\t/; + var match = reg.exec(str); + return match ? match.index : -1; + } +}; + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * xss + * + * @author Zongmin Lei + */ +var DEFAULT = __webpack_require__(3); + +var parser = __webpack_require__(6); + +var FilterXSS = __webpack_require__(12); +/** + * filter xss function + * + * @param {String} html + * @param {Object} options { whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml } + * @return {String} + */ + + +function filterXSS(html, options) { + var xss = new FilterXSS(options); + return xss.process(html); +} + +exports = module.exports = filterXSS; +exports.filterXSS = filterXSS; +exports.FilterXSS = FilterXSS; + +for (var i in DEFAULT) { + exports[i] = DEFAULT[i]; +} + +for (var i in parser) { + exports[i] = parser[i]; +} // using `xss` on the browser, output `filterXSS` to the globals + + +if (typeof window !== "undefined") { + window.filterXSS = module.exports; +} // using `xss` on the WebWorker, output `filterXSS` to the globals + + +function isWorkerEnv() { + return typeof self !== 'undefined' && typeof DedicatedWorkerGlobalScope !== 'undefined' && self instanceof DedicatedWorkerGlobalScope; +} + +if (isWorkerEnv()) { + self.filterXSS = module.exports; +} + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * default settings + * + * @author Zongmin Lei + */ +var FilterCSS = __webpack_require__(0).FilterCSS; + +var getDefaultCSSWhiteList = __webpack_require__(0).getDefaultWhiteList; + +var _ = __webpack_require__(1); + +function getDefaultWhiteList() { + return { + a: ["target", "href", "title"], + abbr: ["title"], + address: [], + area: ["shape", "coords", "href", "alt"], + article: [], + aside: [], + audio: ["autoplay", "controls", "loop", "preload", "src"], + b: [], + bdi: ["dir"], + bdo: ["dir"], + big: [], + blockquote: ["cite"], + br: [], + caption: [], + center: [], + cite: [], + code: [], + col: ["align", "valign", "span", "width"], + colgroup: ["align", "valign", "span", "width"], + dd: [], + del: ["datetime"], + details: ["open"], + div: [], + dl: [], + dt: [], + em: [], + font: ["color", "size", "face"], + footer: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + header: [], + hr: [], + i: [], + img: ["src", "alt", "title", "width", "height"], + ins: ["datetime"], + li: [], + mark: [], + nav: [], + ol: [], + p: [], + pre: [], + s: [], + section: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + table: ["width", "border", "align", "valign"], + tbody: ["align", "valign"], + td: ["width", "rowspan", "colspan", "align", "valign"], + tfoot: ["align", "valign"], + th: ["width", "rowspan", "colspan", "align", "valign"], + thead: ["align", "valign"], + tr: ["rowspan", "align", "valign"], + tt: [], + u: [], + ul: [], + video: ["autoplay", "controls", "loop", "preload", "src", "height", "width"] + }; +} + +var defaultCSSFilter = new FilterCSS(); +/** + * default onTag function + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ + +function onTag(tag, html, options) {} // do nothing + +/** + * default onIgnoreTag function + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ + + +function onIgnoreTag(tag, html, options) {} // do nothing + +/** + * default onTagAttr function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ + + +function onTagAttr(tag, name, value) {} // do nothing + +/** + * default onIgnoreTagAttr function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ + + +function onIgnoreTagAttr(tag, name, value) {} // do nothing + +/** + * default escapeHtml function + * + * @param {String} html + */ + + +function escapeHtml(html) { + return html.replace(REGEXP_LT, "<").replace(REGEXP_GT, ">"); +} +/** + * default safeAttrValue function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @param {Object} cssFilter + * @return {String} + */ + + +function safeAttrValue(tag, name, value, cssFilter) { + // unescape attribute value firstly + value = friendlyAttrValue(value); + + if (name === "href" || name === "src") { + // filter `href` and `src` attribute + // only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#` + value = _.trim(value); + if (value === "#") return "#"; + + if (!(value.substr(0, 7) === "http://" || value.substr(0, 8) === "https://" || value.substr(0, 7) === "mailto:" || value.substr(0, 4) === "tel:" || value[0] === "#" || value[0] === "/")) { + return ""; + } + } else if (name === "background") { + // filter `background` attribute (maybe no use) + // `javascript:` + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ""; + } + } else if (name === "style") { + // `expression()` + REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) { + return ""; + } // `url()` + + + REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) { + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ""; + } + } + + if (cssFilter !== false) { + cssFilter = cssFilter || defaultCSSFilter; + value = cssFilter.process(value); + } + } // escape `<>"` before returns + + + value = escapeAttrValue(value); + return value; +} // RegExp list + + +var REGEXP_LT = //g; +var REGEXP_QUOTE = /"/g; +var REGEXP_QUOTE_2 = /"/g; +var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim; +var REGEXP_ATTR_VALUE_COLON = /:?/gim; +var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim; +var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm; +var REGEXP_DEFAULT_ON_TAG_ATTR_4 = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi; +var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi; +var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi; +var REGEXP_DEFAULT_ON_TAG_ATTR_7 = /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi; +var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi; +/** + * escape doube quote + * + * @param {String} str + * @return {String} str + */ + +function escapeQuote(str) { + return str.replace(REGEXP_QUOTE, """); +} +/** + * unescape double quote + * + * @param {String} str + * @return {String} str + */ + + +function unescapeQuote(str) { + return str.replace(REGEXP_QUOTE_2, '"'); +} +/** + * escape html entities + * + * @param {String} str + * @return {String} + */ + + +function escapeHtmlEntities(str) { + return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) { + return code[0] === "x" || code[0] === "X" ? String.fromCharCode(parseInt(code.substr(1), 16)) : String.fromCharCode(parseInt(code, 10)); + }); +} +/** + * escape html5 new danger entities + * + * @param {String} str + * @return {String} + */ + + +function escapeDangerHtml5Entities(str) { + return str.replace(REGEXP_ATTR_VALUE_COLON, ":").replace(REGEXP_ATTR_VALUE_NEWLINE, " "); +} +/** + * clear nonprintable characters + * + * @param {String} str + * @return {String} + */ + + +function clearNonPrintableCharacter(str) { + var str2 = ""; + + for (var i = 0, len = str.length; i < len; i++) { + str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i); + } + + return _.trim(str2); +} +/** + * get friendly attribute value + * + * @param {String} str + * @return {String} + */ + + +function friendlyAttrValue(str) { + str = unescapeQuote(str); + str = escapeHtmlEntities(str); + str = escapeDangerHtml5Entities(str); + str = clearNonPrintableCharacter(str); + return str; +} +/** + * unescape attribute value + * + * @param {String} str + * @return {String} + */ + + +function escapeAttrValue(str) { + str = escapeQuote(str); + str = escapeHtml(str); + return str; +} +/** + * `onIgnoreTag` function for removing all the tags that are not in whitelist + */ + + +function onIgnoreTagStripAll() { + return ""; +} +/** + * remove tag body + * specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional) + * + * @param {array} tags + * @param {function} next + */ + + +function StripTagBody(tags, next) { + if (typeof next !== "function") { + next = function next() {}; + } + + var isRemoveAllTag = !Array.isArray(tags); + + function isRemoveTag(tag) { + if (isRemoveAllTag) return true; + return _.indexOf(tags, tag) !== -1; + } + + var removeList = []; + var posStart = false; + return { + onIgnoreTag: function onIgnoreTag(tag, html, options) { + if (isRemoveTag(tag)) { + if (options.isClosing) { + var ret = "[/removed]"; + var end = options.position + ret.length; + removeList.push([posStart !== false ? posStart : options.position, end]); + posStart = false; + return ret; + } else { + if (!posStart) { + posStart = options.position; + } + + return "[removed]"; + } + } else { + return next(tag, html, options); + } + }, + remove: function remove(html) { + var rethtml = ""; + var lastPos = 0; + + _.forEach(removeList, function (pos) { + rethtml += html.slice(lastPos, pos[0]); + lastPos = pos[1]; + }); + + rethtml += html.slice(lastPos); + return rethtml; + } + }; +} +/** + * remove html comments + * + * @param {String} html + * @return {String} + */ + + +function stripCommentTag(html) { + return html.replace(STRIP_COMMENT_TAG_REGEXP, ""); +} + +var STRIP_COMMENT_TAG_REGEXP = //g; +/** + * remove invisible characters + * + * @param {String} html + * @return {String} + */ + +function stripBlankChar(html) { + var chars = html.split(""); + chars = chars.filter(function (_char) { + var c = _char.charCodeAt(0); + + if (c === 127) return false; + + if (c <= 31) { + if (c === 10 || c === 13) return true; + return false; + } + + return true; + }); + return chars.join(""); +} + +exports.whiteList = getDefaultWhiteList(); +exports.getDefaultWhiteList = getDefaultWhiteList; +exports.onTag = onTag; +exports.onIgnoreTag = onIgnoreTag; +exports.onTagAttr = onTagAttr; +exports.onIgnoreTagAttr = onIgnoreTagAttr; +exports.safeAttrValue = safeAttrValue; +exports.escapeHtml = escapeHtml; +exports.escapeQuote = escapeQuote; +exports.unescapeQuote = unescapeQuote; +exports.escapeHtmlEntities = escapeHtmlEntities; +exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities; +exports.clearNonPrintableCharacter = clearNonPrintableCharacter; +exports.friendlyAttrValue = friendlyAttrValue; +exports.escapeAttrValue = escapeAttrValue; +exports.onIgnoreTagStripAll = onIgnoreTagStripAll; +exports.StripTagBody = StripTagBody; +exports.stripCommentTag = stripCommentTag; +exports.stripBlankChar = stripBlankChar; +exports.cssFilter = defaultCSSFilter; +exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList; + +/***/ }), +/* 4 */ +/***/ (function(module, exports) { + +/** + * cssfilter + * + * @author 老雷 + */ +function getDefaultWhiteList() { + // 白名单值说明: + // true: 允许该属性 + // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许 + // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许 + // 除上面列出的值外均表示不允许 + var whiteList = {}; + whiteList['align-content'] = false; // default: auto + + whiteList['align-items'] = false; // default: auto + + whiteList['align-self'] = false; // default: auto + + whiteList['alignment-adjust'] = false; // default: auto + + whiteList['alignment-baseline'] = false; // default: baseline + + whiteList['all'] = false; // default: depending on individual properties + + whiteList['anchor-point'] = false; // default: none + + whiteList['animation'] = false; // default: depending on individual properties + + whiteList['animation-delay'] = false; // default: 0 + + whiteList['animation-direction'] = false; // default: normal + + whiteList['animation-duration'] = false; // default: 0 + + whiteList['animation-fill-mode'] = false; // default: none + + whiteList['animation-iteration-count'] = false; // default: 1 + + whiteList['animation-name'] = false; // default: none + + whiteList['animation-play-state'] = false; // default: running + + whiteList['animation-timing-function'] = false; // default: ease + + whiteList['azimuth'] = false; // default: center + + whiteList['backface-visibility'] = false; // default: visible + + whiteList['background'] = true; // default: depending on individual properties + + whiteList['background-attachment'] = true; // default: scroll + + whiteList['background-clip'] = true; // default: border-box + + whiteList['background-color'] = true; // default: transparent + + whiteList['background-image'] = true; // default: none + + whiteList['background-origin'] = true; // default: padding-box + + whiteList['background-position'] = true; // default: 0% 0% + + whiteList['background-repeat'] = true; // default: repeat + + whiteList['background-size'] = true; // default: auto + + whiteList['baseline-shift'] = false; // default: baseline + + whiteList['binding'] = false; // default: none + + whiteList['bleed'] = false; // default: 6pt + + whiteList['bookmark-label'] = false; // default: content() + + whiteList['bookmark-level'] = false; // default: none + + whiteList['bookmark-state'] = false; // default: open + + whiteList['border'] = true; // default: depending on individual properties + + whiteList['border-bottom'] = true; // default: depending on individual properties + + whiteList['border-bottom-color'] = true; // default: current color + + whiteList['border-bottom-left-radius'] = true; // default: 0 + + whiteList['border-bottom-right-radius'] = true; // default: 0 + + whiteList['border-bottom-style'] = true; // default: none + + whiteList['border-bottom-width'] = true; // default: medium + + whiteList['border-collapse'] = true; // default: separate + + whiteList['border-color'] = true; // default: depending on individual properties + + whiteList['border-image'] = true; // default: none + + whiteList['border-image-outset'] = true; // default: 0 + + whiteList['border-image-repeat'] = true; // default: stretch + + whiteList['border-image-slice'] = true; // default: 100% + + whiteList['border-image-source'] = true; // default: none + + whiteList['border-image-width'] = true; // default: 1 + + whiteList['border-left'] = true; // default: depending on individual properties + + whiteList['border-left-color'] = true; // default: current color + + whiteList['border-left-style'] = true; // default: none + + whiteList['border-left-width'] = true; // default: medium + + whiteList['border-radius'] = true; // default: 0 + + whiteList['border-right'] = true; // default: depending on individual properties + + whiteList['border-right-color'] = true; // default: current color + + whiteList['border-right-style'] = true; // default: none + + whiteList['border-right-width'] = true; // default: medium + + whiteList['border-spacing'] = true; // default: 0 + + whiteList['border-style'] = true; // default: depending on individual properties + + whiteList['border-top'] = true; // default: depending on individual properties + + whiteList['border-top-color'] = true; // default: current color + + whiteList['border-top-left-radius'] = true; // default: 0 + + whiteList['border-top-right-radius'] = true; // default: 0 + + whiteList['border-top-style'] = true; // default: none + + whiteList['border-top-width'] = true; // default: medium + + whiteList['border-width'] = true; // default: depending on individual properties + + whiteList['bottom'] = false; // default: auto + + whiteList['box-decoration-break'] = true; // default: slice + + whiteList['box-shadow'] = true; // default: none + + whiteList['box-sizing'] = true; // default: content-box + + whiteList['box-snap'] = true; // default: none + + whiteList['box-suppress'] = true; // default: show + + whiteList['break-after'] = true; // default: auto + + whiteList['break-before'] = true; // default: auto + + whiteList['break-inside'] = true; // default: auto + + whiteList['caption-side'] = false; // default: top + + whiteList['chains'] = false; // default: none + + whiteList['clear'] = true; // default: none + + whiteList['clip'] = false; // default: auto + + whiteList['clip-path'] = false; // default: none + + whiteList['clip-rule'] = false; // default: nonzero + + whiteList['color'] = true; // default: implementation dependent + + whiteList['color-interpolation-filters'] = true; // default: auto + + whiteList['column-count'] = false; // default: auto + + whiteList['column-fill'] = false; // default: balance + + whiteList['column-gap'] = false; // default: normal + + whiteList['column-rule'] = false; // default: depending on individual properties + + whiteList['column-rule-color'] = false; // default: current color + + whiteList['column-rule-style'] = false; // default: medium + + whiteList['column-rule-width'] = false; // default: medium + + whiteList['column-span'] = false; // default: none + + whiteList['column-width'] = false; // default: auto + + whiteList['columns'] = false; // default: depending on individual properties + + whiteList['contain'] = false; // default: none + + whiteList['content'] = false; // default: normal + + whiteList['counter-increment'] = false; // default: none + + whiteList['counter-reset'] = false; // default: none + + whiteList['counter-set'] = false; // default: none + + whiteList['crop'] = false; // default: auto + + whiteList['cue'] = false; // default: depending on individual properties + + whiteList['cue-after'] = false; // default: none + + whiteList['cue-before'] = false; // default: none + + whiteList['cursor'] = false; // default: auto + + whiteList['direction'] = false; // default: ltr + + whiteList['display'] = true; // default: depending on individual properties + + whiteList['display-inside'] = true; // default: auto + + whiteList['display-list'] = true; // default: none + + whiteList['display-outside'] = true; // default: inline-level + + whiteList['dominant-baseline'] = false; // default: auto + + whiteList['elevation'] = false; // default: level + + whiteList['empty-cells'] = false; // default: show + + whiteList['filter'] = false; // default: none + + whiteList['flex'] = false; // default: depending on individual properties + + whiteList['flex-basis'] = false; // default: auto + + whiteList['flex-direction'] = false; // default: row + + whiteList['flex-flow'] = false; // default: depending on individual properties + + whiteList['flex-grow'] = false; // default: 0 + + whiteList['flex-shrink'] = false; // default: 1 + + whiteList['flex-wrap'] = false; // default: nowrap + + whiteList['float'] = false; // default: none + + whiteList['float-offset'] = false; // default: 0 0 + + whiteList['flood-color'] = false; // default: black + + whiteList['flood-opacity'] = false; // default: 1 + + whiteList['flow-from'] = false; // default: none + + whiteList['flow-into'] = false; // default: none + + whiteList['font'] = true; // default: depending on individual properties + + whiteList['font-family'] = true; // default: implementation dependent + + whiteList['font-feature-settings'] = true; // default: normal + + whiteList['font-kerning'] = true; // default: auto + + whiteList['font-language-override'] = true; // default: normal + + whiteList['font-size'] = true; // default: medium + + whiteList['font-size-adjust'] = true; // default: none + + whiteList['font-stretch'] = true; // default: normal + + whiteList['font-style'] = true; // default: normal + + whiteList['font-synthesis'] = true; // default: weight style + + whiteList['font-variant'] = true; // default: normal + + whiteList['font-variant-alternates'] = true; // default: normal + + whiteList['font-variant-caps'] = true; // default: normal + + whiteList['font-variant-east-asian'] = true; // default: normal + + whiteList['font-variant-ligatures'] = true; // default: normal + + whiteList['font-variant-numeric'] = true; // default: normal + + whiteList['font-variant-position'] = true; // default: normal + + whiteList['font-weight'] = true; // default: normal + + whiteList['grid'] = false; // default: depending on individual properties + + whiteList['grid-area'] = false; // default: depending on individual properties + + whiteList['grid-auto-columns'] = false; // default: auto + + whiteList['grid-auto-flow'] = false; // default: none + + whiteList['grid-auto-rows'] = false; // default: auto + + whiteList['grid-column'] = false; // default: depending on individual properties + + whiteList['grid-column-end'] = false; // default: auto + + whiteList['grid-column-start'] = false; // default: auto + + whiteList['grid-row'] = false; // default: depending on individual properties + + whiteList['grid-row-end'] = false; // default: auto + + whiteList['grid-row-start'] = false; // default: auto + + whiteList['grid-template'] = false; // default: depending on individual properties + + whiteList['grid-template-areas'] = false; // default: none + + whiteList['grid-template-columns'] = false; // default: none + + whiteList['grid-template-rows'] = false; // default: none + + whiteList['hanging-punctuation'] = false; // default: none + + whiteList['height'] = true; // default: auto + + whiteList['hyphens'] = false; // default: manual + + whiteList['icon'] = false; // default: auto + + whiteList['image-orientation'] = false; // default: auto + + whiteList['image-resolution'] = false; // default: normal + + whiteList['ime-mode'] = false; // default: auto + + whiteList['initial-letters'] = false; // default: normal + + whiteList['inline-box-align'] = false; // default: last + + whiteList['justify-content'] = false; // default: auto + + whiteList['justify-items'] = false; // default: auto + + whiteList['justify-self'] = false; // default: auto + + whiteList['left'] = false; // default: auto + + whiteList['letter-spacing'] = true; // default: normal + + whiteList['lighting-color'] = true; // default: white + + whiteList['line-box-contain'] = false; // default: block inline replaced + + whiteList['line-break'] = false; // default: auto + + whiteList['line-grid'] = false; // default: match-parent + + whiteList['line-height'] = false; // default: normal + + whiteList['line-snap'] = false; // default: none + + whiteList['line-stacking'] = false; // default: depending on individual properties + + whiteList['line-stacking-ruby'] = false; // default: exclude-ruby + + whiteList['line-stacking-shift'] = false; // default: consider-shifts + + whiteList['line-stacking-strategy'] = false; // default: inline-line-height + + whiteList['list-style'] = true; // default: depending on individual properties + + whiteList['list-style-image'] = true; // default: none + + whiteList['list-style-position'] = true; // default: outside + + whiteList['list-style-type'] = true; // default: disc + + whiteList['margin'] = true; // default: depending on individual properties + + whiteList['margin-bottom'] = true; // default: 0 + + whiteList['margin-left'] = true; // default: 0 + + whiteList['margin-right'] = true; // default: 0 + + whiteList['margin-top'] = true; // default: 0 + + whiteList['marker-offset'] = false; // default: auto + + whiteList['marker-side'] = false; // default: list-item + + whiteList['marks'] = false; // default: none + + whiteList['mask'] = false; // default: border-box + + whiteList['mask-box'] = false; // default: see individual properties + + whiteList['mask-box-outset'] = false; // default: 0 + + whiteList['mask-box-repeat'] = false; // default: stretch + + whiteList['mask-box-slice'] = false; // default: 0 fill + + whiteList['mask-box-source'] = false; // default: none + + whiteList['mask-box-width'] = false; // default: auto + + whiteList['mask-clip'] = false; // default: border-box + + whiteList['mask-image'] = false; // default: none + + whiteList['mask-origin'] = false; // default: border-box + + whiteList['mask-position'] = false; // default: center + + whiteList['mask-repeat'] = false; // default: no-repeat + + whiteList['mask-size'] = false; // default: border-box + + whiteList['mask-source-type'] = false; // default: auto + + whiteList['mask-type'] = false; // default: luminance + + whiteList['max-height'] = true; // default: none + + whiteList['max-lines'] = false; // default: none + + whiteList['max-width'] = true; // default: none + + whiteList['min-height'] = true; // default: 0 + + whiteList['min-width'] = true; // default: 0 + + whiteList['move-to'] = false; // default: normal + + whiteList['nav-down'] = false; // default: auto + + whiteList['nav-index'] = false; // default: auto + + whiteList['nav-left'] = false; // default: auto + + whiteList['nav-right'] = false; // default: auto + + whiteList['nav-up'] = false; // default: auto + + whiteList['object-fit'] = false; // default: fill + + whiteList['object-position'] = false; // default: 50% 50% + + whiteList['opacity'] = false; // default: 1 + + whiteList['order'] = false; // default: 0 + + whiteList['orphans'] = false; // default: 2 + + whiteList['outline'] = false; // default: depending on individual properties + + whiteList['outline-color'] = false; // default: invert + + whiteList['outline-offset'] = false; // default: 0 + + whiteList['outline-style'] = false; // default: none + + whiteList['outline-width'] = false; // default: medium + + whiteList['overflow'] = false; // default: depending on individual properties + + whiteList['overflow-wrap'] = false; // default: normal + + whiteList['overflow-x'] = false; // default: visible + + whiteList['overflow-y'] = false; // default: visible + + whiteList['padding'] = true; // default: depending on individual properties + + whiteList['padding-bottom'] = true; // default: 0 + + whiteList['padding-left'] = true; // default: 0 + + whiteList['padding-right'] = true; // default: 0 + + whiteList['padding-top'] = true; // default: 0 + + whiteList['page'] = false; // default: auto + + whiteList['page-break-after'] = false; // default: auto + + whiteList['page-break-before'] = false; // default: auto + + whiteList['page-break-inside'] = false; // default: auto + + whiteList['page-policy'] = false; // default: start + + whiteList['pause'] = false; // default: implementation dependent + + whiteList['pause-after'] = false; // default: implementation dependent + + whiteList['pause-before'] = false; // default: implementation dependent + + whiteList['perspective'] = false; // default: none + + whiteList['perspective-origin'] = false; // default: 50% 50% + + whiteList['pitch'] = false; // default: medium + + whiteList['pitch-range'] = false; // default: 50 + + whiteList['play-during'] = false; // default: auto + + whiteList['position'] = false; // default: static + + whiteList['presentation-level'] = false; // default: 0 + + whiteList['quotes'] = false; // default: text + + whiteList['region-fragment'] = false; // default: auto + + whiteList['resize'] = false; // default: none + + whiteList['rest'] = false; // default: depending on individual properties + + whiteList['rest-after'] = false; // default: none + + whiteList['rest-before'] = false; // default: none + + whiteList['richness'] = false; // default: 50 + + whiteList['right'] = false; // default: auto + + whiteList['rotation'] = false; // default: 0 + + whiteList['rotation-point'] = false; // default: 50% 50% + + whiteList['ruby-align'] = false; // default: auto + + whiteList['ruby-merge'] = false; // default: separate + + whiteList['ruby-position'] = false; // default: before + + whiteList['shape-image-threshold'] = false; // default: 0.0 + + whiteList['shape-outside'] = false; // default: none + + whiteList['shape-margin'] = false; // default: 0 + + whiteList['size'] = false; // default: auto + + whiteList['speak'] = false; // default: auto + + whiteList['speak-as'] = false; // default: normal + + whiteList['speak-header'] = false; // default: once + + whiteList['speak-numeral'] = false; // default: continuous + + whiteList['speak-punctuation'] = false; // default: none + + whiteList['speech-rate'] = false; // default: medium + + whiteList['stress'] = false; // default: 50 + + whiteList['string-set'] = false; // default: none + + whiteList['tab-size'] = false; // default: 8 + + whiteList['table-layout'] = false; // default: auto + + whiteList['text-align'] = true; // default: start + + whiteList['text-align-last'] = true; // default: auto + + whiteList['text-combine-upright'] = true; // default: none + + whiteList['text-decoration'] = true; // default: none + + whiteList['text-decoration-color'] = true; // default: currentColor + + whiteList['text-decoration-line'] = true; // default: none + + whiteList['text-decoration-skip'] = true; // default: objects + + whiteList['text-decoration-style'] = true; // default: solid + + whiteList['text-emphasis'] = true; // default: depending on individual properties + + whiteList['text-emphasis-color'] = true; // default: currentColor + + whiteList['text-emphasis-position'] = true; // default: over right + + whiteList['text-emphasis-style'] = true; // default: none + + whiteList['text-height'] = true; // default: auto + + whiteList['text-indent'] = true; // default: 0 + + whiteList['text-justify'] = true; // default: auto + + whiteList['text-orientation'] = true; // default: mixed + + whiteList['text-overflow'] = true; // default: clip + + whiteList['text-shadow'] = true; // default: none + + whiteList['text-space-collapse'] = true; // default: collapse + + whiteList['text-transform'] = true; // default: none + + whiteList['text-underline-position'] = true; // default: auto + + whiteList['text-wrap'] = true; // default: normal + + whiteList['top'] = false; // default: auto + + whiteList['transform'] = false; // default: none + + whiteList['transform-origin'] = false; // default: 50% 50% 0 + + whiteList['transform-style'] = false; // default: flat + + whiteList['transition'] = false; // default: depending on individual properties + + whiteList['transition-delay'] = false; // default: 0s + + whiteList['transition-duration'] = false; // default: 0s + + whiteList['transition-property'] = false; // default: all + + whiteList['transition-timing-function'] = false; // default: ease + + whiteList['unicode-bidi'] = false; // default: normal + + whiteList['vertical-align'] = false; // default: baseline + + whiteList['visibility'] = false; // default: visible + + whiteList['voice-balance'] = false; // default: center + + whiteList['voice-duration'] = false; // default: auto + + whiteList['voice-family'] = false; // default: implementation dependent + + whiteList['voice-pitch'] = false; // default: medium + + whiteList['voice-range'] = false; // default: medium + + whiteList['voice-rate'] = false; // default: normal + + whiteList['voice-stress'] = false; // default: normal + + whiteList['voice-volume'] = false; // default: medium + + whiteList['volume'] = false; // default: medium + + whiteList['white-space'] = false; // default: normal + + whiteList['widows'] = false; // default: 2 + + whiteList['width'] = true; // default: auto + + whiteList['will-change'] = false; // default: auto + + whiteList['word-break'] = true; // default: normal + + whiteList['word-spacing'] = true; // default: normal + + whiteList['word-wrap'] = true; // default: normal + + whiteList['wrap-flow'] = false; // default: auto + + whiteList['wrap-through'] = false; // default: wrap + + whiteList['writing-mode'] = false; // default: horizontal-tb + + whiteList['z-index'] = false; // default: auto + + return whiteList; +} +/** + * 匹配到白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ + + +function onAttr(name, value, options) {} // do nothing + +/** + * 匹配到不在白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ + + +function onIgnoreAttr(name, value, options) {// do nothing +} + +var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img; +/** + * 过滤属性值 + * + * @param {String} name + * @param {String} value + * @return {String} + */ + +function safeAttrValue(name, value) { + if (REGEXP_URL_JAVASCRIPT.test(value)) return ''; + return value; +} + +exports.whiteList = getDefaultWhiteList(); +exports.getDefaultWhiteList = getDefaultWhiteList; +exports.onAttr = onAttr; +exports.onIgnoreAttr = onIgnoreAttr; +exports.safeAttrValue = safeAttrValue; + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +module.exports = { + indexOf: function indexOf(arr, item) { + var i, j; + + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + + return -1; + }, + forEach: function forEach(arr, fn, scope) { + var i, j; + + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function trim(str) { + if (String.prototype.trim) { + return str.trim(); + } + + return str.replace(/(^\s*)|(\s*$)/g, ''); + }, + trimRight: function trimRight(str) { + if (String.prototype.trimRight) { + return str.trimRight(); + } + + return str.replace(/(\s*$)/g, ''); + } +}; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Simple HTML Parser + * + * @author Zongmin Lei + */ +var _ = __webpack_require__(1); +/** + * get tag name + * + * @param {String} html e.g. '' + * @return {String} + */ + + +function getTagName(html) { + var i = _.spaceIndex(html); + + if (i === -1) { + var tagName = html.slice(1, -1); + } else { + var tagName = html.slice(1, i + 1); + } + + tagName = _.trim(tagName).toLowerCase(); + if (tagName.slice(0, 1) === "/") tagName = tagName.slice(1); + if (tagName.slice(-1) === "/") tagName = tagName.slice(0, -1); + return tagName; +} +/** + * is close tag? + * + * @param {String} html 如:'' + * @return {Boolean} + */ + + +function isClosing(html) { + return html.slice(0, 2) === "") { + rethtml += escapeHtml(html.slice(lastPos, tagStart)); + currentHtml = html.slice(tagStart, currentPos + 1); + currentTagName = getTagName(currentHtml); + rethtml += onTag(tagStart, rethtml.length, currentTagName, currentHtml, isClosing(currentHtml)); + lastPos = currentPos + 1; + tagStart = false; + continue; + } + + if ((c === '"' || c === "'") && html.charAt(currentPos - 1) === "=") { + quoteStart = c; + continue; + } + } else { + if (c === quoteStart) { + quoteStart = false; + continue; + } + } + } + } + + if (lastPos < html.length) { + rethtml += escapeHtml(html.substr(lastPos)); + } + + return rethtml; +} + +var REGEXP_ILLEGAL_ATTR_NAME = /[^a-zA-Z0-9_:\.\-]/gim; +/** + * parse input attributes and returns processed attributes + * + * @param {String} html e.g. `href="#" target="_blank"` + * @param {Function} onAttr e.g. `function (name, value)` + * @return {String} + */ + +function parseAttr(html, onAttr) { + "user strict"; + + var lastPos = 0; + var retAttrs = []; + var tmpName = false; + var len = html.length; + + function addAttr(name, value) { + name = _.trim(name); + name = name.replace(REGEXP_ILLEGAL_ATTR_NAME, "").toLowerCase(); + if (name.length < 1) return; + var ret = onAttr(name, value || ""); + if (ret) retAttrs.push(ret); + } // 逐个分析字符 + + + for (var i = 0; i < len; i++) { + var c = html.charAt(i); + var v, j; + + if (tmpName === false && c === "=") { + tmpName = html.slice(lastPos, i); + lastPos = i + 1; + continue; + } + + if (tmpName !== false) { + if (i === lastPos && (c === '"' || c === "'") && html.charAt(i - 1) === "=") { + j = html.indexOf(c, i + 1); + + if (j === -1) { + break; + } else { + v = _.trim(html.slice(lastPos + 1, j)); + addAttr(tmpName, v); + tmpName = false; + i = j; + lastPos = i + 1; + continue; + } + } + } + + if (/\s|\n|\t/.test(c)) { + html = html.replace(/\s|\n|\t/g, " "); + + if (tmpName === false) { + j = findNextEqual(html, i); + + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + addAttr(v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + i = j - 1; + continue; + } + } else { + j = findBeforeEqual(html, i - 1); + + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + v = stripQuoteWrap(v); + addAttr(tmpName, v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + continue; + } + } + } + } + + if (lastPos < html.length) { + if (tmpName === false) { + addAttr(html.slice(lastPos)); + } else { + addAttr(tmpName, stripQuoteWrap(_.trim(html.slice(lastPos)))); + } + } + + return _.trim(retAttrs.join(" ")); +} + +function findNextEqual(str, i) { + for (; i < str.length; i++) { + var c = str[i]; + if (c === " ") continue; + if (c === "=") return i; + return -1; + } +} + +function findBeforeEqual(str, i) { + for (; i > 0; i--) { + var c = str[i]; + if (c === " ") continue; + if (c === "=") return i; + return -1; + } +} + +function isQuoteWrapString(text) { + if (text[0] === '"' && text[text.length - 1] === '"' || text[0] === "'" && text[text.length - 1] === "'") { + return true; + } else { + return false; + } +} + +function stripQuoteWrap(text) { + if (isQuoteWrapString(text)) { + return text.substr(1, text.length - 2); + } else { + return text; + } +} + +exports.parseTag = parseTag; +exports.parseAttr = parseAttr; + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +/** + * marked - a markdown parser + * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +; + +(function (root) { + 'use strict'; + /** + * Block-Level Grammar + */ + + var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/, + nptable: noop, + blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, + list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: '^ {0,3}(?:' // optional indentation + + '<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?\\?>\\n*' // (3) + + '|\\n*' // (4) + + '|\\n*' // (5) + + '|)[\\s\\S]*?(?:\\n{2,}|$)' // (6) + + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag + + ')', + def: /^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/, + table: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/, + text: /^[^\n]+/ + }; + block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/; + block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/; + block.def = edit(block.def).replace('label', block._label).replace('title', block._title).getRegex(); + block.bullet = /(?:[*+-]|\d{1,9}\.)/; + block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/; + block.item = edit(block.item, 'gm').replace(/bull/g, block.bullet).getRegex(); + block.list = edit(block.list).replace(/bull/g, block.bullet).replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))').replace('def', '\\n+(?=' + block.def.source + ')').getRegex(); + block._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + '|track|ul'; + block._comment = //; + block.html = edit(block.html, 'i').replace('comment', block._comment).replace('tag', block._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(); + block.paragraph = edit(block.paragraph).replace('hr', block.hr).replace('heading', block.heading).replace('lheading', block.lheading).replace('tag', block._tag) // pars can be interrupted by type (6) html blocks + .getRegex(); + block.blockquote = edit(block.blockquote).replace('paragraph', block.paragraph).getRegex(); + /** + * Normal Block Grammar + */ + + block.normal = merge({}, block); + /** + * GFM Block Grammar + */ + + block.gfm = merge({}, block.normal, { + fences: /^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ + }); + block.gfm.paragraph = edit(block.paragraph).replace('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|' + block.list.source.replace('\\1', '\\3') + '|').getRegex(); + /** + * GFM + Tables Block Grammar + */ + + block.tables = merge({}, block.gfm, { + nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/, + table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/ + }); + /** + * Pedantic grammar + */ + + block.pedantic = merge({}, block.normal, { + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', block._comment).replace(/tag/g, '(?!(?:' + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/ + }); + /** + * Block Lexer + */ + + function Lexer(options) { + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.pedantic) { + this.rules = block.pedantic; + } else if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } + } + /** + * Expose Block Rules + */ + + + Lexer.rules = block; + /** + * Static Lex Method + */ + + Lexer.lex = function (src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); + }; + /** + * Preprocessing + */ + + + Lexer.prototype.lex = function (src) { + src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, ' ').replace(/\u00a0/g, ' ').replace(/\u2424/g, '\n'); + return this.token(src, true); + }; + /** + * Lexing + */ + + + Lexer.prototype.token = function (src, top) { + src = src.replace(/^ +$/gm, ''); + var next, loose, cap, bull, b, item, listStart, listItems, t, space, i, tag, l, isordered, istask, ischecked; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } // code + + + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic ? rtrim(cap, '\n') : cap + }); + continue; + } // fences (gfm) + + + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2] ? cap[2].trim() : cap[2], + text: cap[3] || '' + }); + continue; + } // heading + + + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } // table no leading pipe (gfm) + + + if (cap = this.rules.nptable.exec(src)) { + item = { + type: 'table', + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells(item.cells[i], item.header.length); + } + + this.tokens.push(item); + continue; + } + } // hr + + + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } // blockquote + + + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'blockquote_start' + }); + cap = cap[0].replace(/^ *> ?/gm, ''); // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + + this.token(cap, top); + this.tokens.push({ + type: 'blockquote_end' + }); + continue; + } // list + + + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + isordered = bull.length > 1; + listStart = { + type: 'list_start', + ordered: isordered, + start: isordered ? +bull : '', + loose: false + }; + this.tokens.push(listStart); // Get each top-level item. + + cap = cap[0].match(this.rules.item); + listItems = []; + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; // Remove the list item's bullet + // so it is seen as the next token. + + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) */, ''); // Outdent whatever the + // list item contains. Hacky. + + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') : item.replace(/^ {1,4}/gm, ''); + } // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + + + if (i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + + if (bull.length > 1 ? b.length === 1 : b.length > 1 || this.options.smartLists && b !== bull) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + + + loose = next || /\n\n(?!\s*$)/.test(item); + + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + if (loose) { + listStart.loose = true; + } // Check for task list items + + + istask = /^\[[ xX]\] /.test(item); + ischecked = undefined; + + if (istask) { + ischecked = item[1] !== ' '; + item = item.replace(/^\[[ xX]\] +/, ''); + } + + t = { + type: 'list_item_start', + task: istask, + checked: ischecked, + loose: loose + }; + listItems.push(t); + this.tokens.push(t); // Recurse. + + this.token(item, false); + this.tokens.push({ + type: 'list_item_end' + }); + } + + if (listStart.loose) { + l = listItems.length; + i = 0; + + for (; i < l; i++) { + listItems[i].loose = true; + } + } + + this.tokens.push({ + type: 'list_end' + }); + continue; + } // html + + + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize ? 'paragraph' : 'html', + pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } // def + + + if (top && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1); + tag = cap[1].toLowerCase().replace(/\s+/g, ' '); + + if (!this.tokens.links[tag]) { + this.tokens.links[tag] = { + href: cap[2], + title: cap[3] + }; + } + + continue; + } // table (gfm) + + + if (cap = this.rules.table.exec(src)) { + item = { + type: 'table', + header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] + }; + + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ''), item.header.length); + } + + this.tokens.push(item); + continue; + } + } // lheading + + + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } // top-level paragraph + + + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1] + }); + continue; + } // text + + + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; + }; + /** + * Inline-Level Grammar + */ + + + var inline = { + escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, + autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/, + url: noop, + tag: '^comment' + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^', + // CDATA section + link: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/, + reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/, + nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/, + strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/, + em: /^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/, + code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, + br: /^( {2,}|\\)\n(?!\s*$)/, + del: noop, + text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~'; + inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); + inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g; + inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/; + inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/; + inline.autolink = edit(inline.autolink).replace('scheme', inline._scheme).replace('email', inline._email).getRegex(); + inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/; + inline.tag = edit(inline.tag).replace('comment', block._comment).replace('attribute', inline._attribute).getRegex(); + inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/; + inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/; + inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/; + inline.link = edit(inline.link).replace('label', inline._label).replace('href', inline._href).replace('title', inline._title).getRegex(); + inline.reflink = edit(inline.reflink).replace('label', inline._label).getRegex(); + /** + * Normal Inline Grammar + */ + + inline.normal = merge({}, inline); + /** + * Pedantic Inline Grammar + */ + + inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/, + link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline._label).getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline._label).getRegex() + }); + /** + * GFM Inline Grammar + */ + + inline.gfm = merge({}, inline.normal, { + escape: edit(inline.escape).replace('])', '~|])').getRegex(), + _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/, + url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, + _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/, + del: /^~+(?=\S)([\s\S]*?\S)~+/, + text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(cap[0])) { + this.inLink = false; + } + + if (!this.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.inRawBlock = true; + } else if (this.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) { + this.inRawBlock = false; + } + + src = src.substring(cap[0].length); + out += this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]) : cap[0]; + continue; + } // link + + + if (cap = this.rules.link.exec(src)) { + var lastParenIndex = findClosingBracket(cap[2], '()'); + + if (lastParenIndex > -1) { + var linkLen = cap[0].length - (cap[2].length - lastParenIndex) - (cap[3] || '').length; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + + src = src.substring(cap[0].length); + this.inLink = true; + href = cap[2]; + + if (this.options.pedantic) { + link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href); + + if (link) { + href = link[1]; + title = link[3]; + } else { + title = ''; + } + } else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + + href = href.trim().replace(/^<([\s\S]*)>$/, '$1'); + out += this.outputLink(cap, { + href: InlineLexer.escapes(href), + title: InlineLexer.escapes(title) + }); + this.inLink = false; + continue; + } // reflink, nolink + + + if ((cap = this.rules.reflink.exec(src)) || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } // strong + + + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1])); + continue; + } // em + + + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1])); + continue; + } // code + + + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2].trim(), true)); + continue; + } // br + + + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } // del (gfm) + + + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } // autolink + + + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + + if (cap[2] === '@') { + text = escape(this.mangle(cap[1])); + href = 'mailto:' + text; + } else { + text = escape(cap[1]); + href = text; + } + + out += this.renderer.link(href, null, text); + continue; + } // url (gfm) + + + if (!this.inLink && (cap = this.rules.url.exec(src))) { + if (cap[2] === '@') { + text = escape(cap[0]); + href = 'mailto:' + text; + } else { + // do extended autolink path validation + do { + prevCapZero = cap[0]; + cap[0] = this.rules._backpedal.exec(cap[0])[0]; + } while (prevCapZero !== cap[0]); + + text = escape(cap[0]); + + if (cap[1] === 'www.') { + href = 'http://' + text; + } else { + href = text; + } + } + + src = src.substring(cap[0].length); + out += this.renderer.link(href, null, text); + continue; + } // text + + + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + + if (this.inRawBlock) { + out += this.renderer.text(cap[0]); + } else { + out += this.renderer.text(escape(this.smartypants(cap[0]))); + } + + continue; + } + + if (src) { + throw new Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; + }; + + InlineLexer.escapes = function (text) { + return text ? text.replace(InlineLexer.rules._escapes, '$1') : text; + }; + /** + * Compile Link + */ + + + InlineLexer.prototype.outputLink = function (cap, link) { + var href = link.href, + title = link.title ? escape(link.title) : null; + return cap[0].charAt(0) !== '!' ? this.renderer.link(href, title, this.output(cap[1])) : this.renderer.image(href, title, escape(cap[1])); + }; + /** + * Smartypants Transformations + */ + + + InlineLexer.prototype.smartypants = function (text) { + if (!this.options.smartypants) return text; + return text // em-dashes + .replace(/---/g, "\u2014") // en-dashes + .replace(/--/g, "\u2013") // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018") // closing singles & apostrophes + .replace(/'/g, "\u2019") // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201C") // closing doubles + .replace(/"/g, "\u201D") // ellipses + .replace(/\.{3}/g, "\u2026"); + }; + /** + * Mangle Links + */ + + + InlineLexer.prototype.mangle = function (text) { + if (!this.options.mangle) return text; + var out = '', + l = text.length, + i = 0, + ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + + out += '&#' + ch + ';'; + } + + return out; + }; + /** + * Renderer + */ + + + function Renderer(options) { + this.options = options || marked.defaults; + } + + Renderer.prototype.code = function (code, infostring, escaped) { + var lang = (infostring || '').match(/\S*/)[0]; + + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
' + (escaped ? code : escape(code, true)) + '
'; + } + + return '
' + (escaped ? code : escape(code, true)) + '
\n'; + }; + + Renderer.prototype.blockquote = function (quote) { + return '
\n' + quote + '
\n'; + }; + + Renderer.prototype.html = function (html) { + return html; + }; + + Renderer.prototype.heading = function (text, level, raw, slugger) { + if (this.options.headerIds) { + return '' + text + '\n'; + } // ignore IDs + + + return '' + text + '\n'; + }; + + Renderer.prototype.hr = function () { + return this.options.xhtml ? '
\n' : '
\n'; + }; + + Renderer.prototype.list = function (body, ordered, start) { + var type = ordered ? 'ol' : 'ul', + startatt = ordered && start !== 1 ? ' start="' + start + '"' : ''; + return '<' + type + startatt + '>\n' + body + '\n'; + }; + + Renderer.prototype.listitem = function (text) { + return '
  • ' + text + '
  • \n'; + }; + + Renderer.prototype.checkbox = function (checked) { + return ' '; + }; + + Renderer.prototype.paragraph = function (text) { + return '

    ' + text + '

    \n'; + }; + + Renderer.prototype.table = function (header, body) { + if (body) body = '' + body + ''; + return '\n' + '\n' + header + '\n' + body + '
    \n'; + }; + + Renderer.prototype.tablerow = function (content) { + return '\n' + content + '\n'; + }; + + Renderer.prototype.tablecell = function (content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>'; + return tag + content + '\n'; + }; // span level renderer + + + Renderer.prototype.strong = function (text) { + return '' + text + ''; + }; + + Renderer.prototype.em = function (text) { + return '' + text + ''; + }; + + Renderer.prototype.codespan = function (text) { + return '' + text + ''; + }; + + Renderer.prototype.br = function () { + return this.options.xhtml ? '
    ' : '
    '; + }; + + Renderer.prototype.del = function (text) { + return '' + text + ''; + }; + + Renderer.prototype.link = function (href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + + if (href === null) { + return text; + } + + var out = '
    '; + return out; + }; + + Renderer.prototype.image = function (href, title, text) { + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + + if (href === null) { + return text; + } + + var out = '' + text + '' : '>'; + return out; + }; + + Renderer.prototype.text = function (text) { + return text; + }; + /** + * TextRenderer + * returns only the textual part of the token + */ + + + function TextRenderer() {} // no need for block level renderers + + + TextRenderer.prototype.strong = TextRenderer.prototype.em = TextRenderer.prototype.codespan = TextRenderer.prototype.del = TextRenderer.prototype.text = function (text) { + return text; + }; + + TextRenderer.prototype.link = TextRenderer.prototype.image = function (href, title, text) { + return '' + text; + }; + + TextRenderer.prototype.br = function () { + return ''; + }; + /** + * Parsing & Compiling + */ + + + function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer(); + this.renderer = this.options.renderer; + this.renderer.options = this.options; + this.slugger = new Slugger(); + } + /** + * Static Parse Method + */ + + + Parser.parse = function (src, options) { + var parser = new Parser(options); + return parser.parse(src); + }; + /** + * Parse Loop + */ + + + Parser.prototype.parse = function (src) { + this.inline = new InlineLexer(src.links, this.options); // use an InlineLexer with a TextRenderer to extract pure text + + this.inlineText = new InlineLexer(src.links, merge({}, this.options, { + renderer: new TextRenderer() + })); + this.tokens = src.reverse(); + var out = ''; + + while (this.next()) { + out += this.tok(); + } + + return out; + }; + /** + * Next Token + */ + + + Parser.prototype.next = function () { + return this.token = this.tokens.pop(); + }; + /** + * Preview Next Token + */ + + + Parser.prototype.peek = function () { + return this.tokens[this.tokens.length - 1] || 0; + }; + /** + * Parse Text Tokens + */ + + + Parser.prototype.parseText = function () { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); + }; + /** + * Parse Current Token + */ + + + Parser.prototype.tok = function () { + switch (this.token.type) { + case 'space': + { + return ''; + } + + case 'hr': + { + return this.renderer.hr(); + } + + case 'heading': + { + return this.renderer.heading(this.inline.output(this.token.text), this.token.depth, unescape(this.inlineText.output(this.token.text)), this.slugger); + } + + case 'code': + { + return this.renderer.code(this.token.text, this.token.lang, this.token.escaped); + } + + case 'table': + { + var header = '', + body = '', + i, + row, + cell, + j; // header + + cell = ''; + + for (i = 0; i < this.token.header.length; i++) { + cell += this.renderer.tablecell(this.inline.output(this.token.header[i]), { + header: true, + align: this.token.align[i] + }); + } + + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + cell = ''; + + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell(this.inline.output(row[j]), { + header: false, + align: this.token.align[j] + }); + } + + body += this.renderer.tablerow(cell); + } + + return this.renderer.table(header, body); + } + + case 'blockquote_start': + { + body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + + case 'list_start': + { + body = ''; + var ordered = this.token.ordered, + start = this.token.start; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered, start); + } + + case 'list_item_start': + { + body = ''; + var loose = this.token.loose; + var checked = this.token.checked; + var task = this.token.task; + + if (this.token.task) { + body += this.renderer.checkbox(checked); + } + + while (this.next().type !== 'list_item_end') { + body += !loose && this.token.type === 'text' ? this.parseText() : this.tok(); + } + + return this.renderer.listitem(body, task, checked); + } + + case 'html': + { + // TODO parse inline content if parameter markdown=1 + return this.renderer.html(this.token.text); + } + + case 'paragraph': + { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + + case 'text': + { + return this.renderer.paragraph(this.parseText()); + } + + default: + { + var errMsg = 'Token with "' + this.token.type + '" type was not found.'; + + if (this.options.silent) { + console.log(errMsg); + } else { + throw new Error(errMsg); + } + } + } + }; + /** + * Slugger generates header id + */ + + + function Slugger() { + this.seen = {}; + } + /** + * Convert string to unique id + */ + + + Slugger.prototype.slug = function (value) { + var slug = value.toLowerCase().trim().replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-'); + + if (this.seen.hasOwnProperty(slug)) { + var originalSlug = slug; + + do { + this.seen[originalSlug]++; + slug = originalSlug + '-' + this.seen[originalSlug]; + } while (this.seen.hasOwnProperty(slug)); + } + + this.seen[slug] = 0; + return slug; + }; + /** + * Helpers + */ + + + function escape(html, encode) { + if (encode) { + if (escape.escapeTest.test(html)) { + return html.replace(escape.escapeReplace, function (ch) { + return escape.replacements[ch]; + }); + } + } else { + if (escape.escapeTestNoEncode.test(html)) { + return html.replace(escape.escapeReplaceNoEncode, function (ch) { + return escape.replacements[ch]; + }); + } + } + + return html; + } + + escape.escapeTest = /[&<>"']/; + escape.escapeReplace = /[&<>"']/g; + escape.replacements = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + escape.escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/; + escape.escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g; + + function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function (_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1)); + } + + return ''; + }); + } + + function edit(regex, opt) { + regex = regex.source || regex; + opt = opt || ''; + return { + replace: function replace(name, val) { + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return this; + }, + getRegex: function getRegex() { + return new RegExp(regex, opt); + } + }; + } + + function cleanUrl(sanitize, base, href) { + if (sanitize) { + try { + var prot = decodeURIComponent(unescape(href)).replace(/[^\w:]/g, '').toLowerCase(); + } catch (e) { + return null; + } + + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return null; + } + } + + if (base && !originIndependentUrl.test(href)) { + href = resolveUrl(base, href); + } + + try { + href = encodeURI(href).replace(/%25/g, '%'); + } catch (e) { + return null; + } + + return href; + } + + function resolveUrl(base, href) { + if (!baseUrls[' ' + base]) { + // we can ignore everything in base after the last slash of its path component, + // but we might need to add _that_ + // https://tools.ietf.org/html/rfc3986#section-3 + if (/^[^:]+:\/*[^/]*$/.test(base)) { + baseUrls[' ' + base] = base + '/'; + } else { + baseUrls[' ' + base] = rtrim(base, '/', true); + } + } + + base = baseUrls[' ' + base]; + + if (href.slice(0, 2) === '//') { + return base.replace(/:[\s\S]*/, ':') + href; + } else if (href.charAt(0) === '/') { + return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href; + } else { + return base + href; + } + } + + var baseUrls = {}; + var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i; + + function noop() {} + + noop.exec = noop; + + function merge(obj) { + var i = 1, + target, + key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; + } + + function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + var row = tableRow.replace(/\|/g, function (match, offset, str) { + var escaped = false, + curr = offset; + + while (--curr >= 0 && str[curr] === '\\') { + escaped = !escaped; + } + + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } else { + // add space before unescaped | + return ' |'; + } + }), + cells = row.split(/ \|/), + i = 0; + + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) { + cells.push(''); + } + } + + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(/\\\|/g, '|'); + } + + return cells; + } // Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + // /c*$/ is vulnerable to REDOS. + // invert: Remove suffix of non-c chars instead. Default falsey. + + + function rtrim(str, c, invert) { + if (str.length === 0) { + return ''; + } // Length of suffix matching the invert condition. + + + var suffLen = 0; // Step left until we fail to match the invert condition. + + while (suffLen < str.length) { + var currChar = str.charAt(str.length - suffLen - 1); + + if (currChar === c && !invert) { + suffLen++; + } else if (currChar !== c && invert) { + suffLen++; + } else { + break; + } + } + + return str.substr(0, str.length - suffLen); + } + + function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + + var level = 0; + + for (var i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } else if (str[i] === b[0]) { + level++; + } else if (str[i] === b[1]) { + level--; + + if (level < 0) { + return i; + } + } + } + + return -1; + } + /** + * Marked + */ + + + function marked(src, opt, callback) { + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + throw new Error('marked(): input parameter is undefined or null'); + } + + if (typeof src !== 'string') { + throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected'); + } + + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + var highlight = opt.highlight, + tokens, + pending, + i = 0; + + try { + tokens = Lexer.lex(src, opt); + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function done(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + return err ? callback(err) : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function (token) { + if (token.type !== 'code') { + return --pending || done(); + } + + return highlight(token.text, token.lang, function (err, code) { + if (err) return done(err); + + if (code == null || code === token.text) { + return --pending || done(); + } + + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + + if ((opt || marked.defaults).silent) { + return '

    An error occurred:

    ' + escape(e.message + '', true) + '
    '; + } + + throw e; + } + } + /** + * Options + */ + + + marked.options = marked.setOptions = function (opt) { + merge(marked.defaults, opt); + return marked; + }; + + marked.getDefaults = function () { + return { + baseUrl: null, + breaks: false, + gfm: true, + headerIds: true, + headerPrefix: '', + highlight: null, + langPrefix: 'language-', + mangle: true, + pedantic: false, + renderer: new Renderer(), + sanitize: false, + sanitizer: null, + silent: false, + smartLists: false, + smartypants: false, + tables: true, + xhtml: false + }; + }; + + marked.defaults = marked.getDefaults(); + /** + * Expose + */ + + marked.Parser = Parser; + marked.parser = Parser.parse; + marked.Renderer = Renderer; + marked.TextRenderer = TextRenderer; + marked.Lexer = Lexer; + marked.lexer = Lexer.lex; + marked.InlineLexer = InlineLexer; + marked.inlineLexer = InlineLexer.output; + marked.Slugger = Slugger; + marked.parse = marked; + + if ( true && ( false ? undefined : _typeof(exports)) === 'object') { + module.exports = marked; + } else if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () { + return marked; + }).call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else {} +})(this || (typeof window !== 'undefined' ? window : global)); +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(9))) + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderMarkdown", function() { return renderMarkdown; }); +/* harmony import */ var marked__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7); +/* harmony import */ var marked__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(marked__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var xss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony import */ var xss__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(xss__WEBPACK_IMPORTED_MODULE_1__); + // @ts-ignore + + +var whiteListNormal; +var whiteListSvg; +var renderMarkdown = function renderMarkdown(content, markedOptions) { + var hassOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (!whiteListNormal) { + whiteListNormal = Object.assign({}, xss__WEBPACK_IMPORTED_MODULE_1___default.a.whiteList, { + "ha-icon": ["icon"] + }); + } + + var whiteList; + + if (hassOptions.allowSvg) { + if (!whiteListSvg) { + whiteListSvg = Object.assign({}, whiteListNormal, { + svg: ["xmlns", "height", "width"], + path: ["transform", "stroke", "d"], + img: ["src"] + }); + } + + whiteList = whiteListSvg; + } else { + whiteList = whiteListNormal; + } + + return xss__WEBPACK_IMPORTED_MODULE_1___default()(marked__WEBPACK_IMPORTED_MODULE_0___default()(content, markedOptions), { + whiteList: whiteList + }); +}; +addEventListener('message', function (e) {var ref = e.data;var type = ref.type;var method = ref.method;var id = ref.id;var params = ref.params;var f,p;if (type === 'RPC' && method) {if (f = __webpack_exports__[method]) {p = Promise.resolve().then(function () { return f.apply(__webpack_exports__, params); });} else {p = Promise.reject('No such method');}p.then(function (result) {postMessage({type: 'RPC',id: id,result: result});}).catch(function (e) {var error = {message: e};if (e.stack) {error.message = e.message;error.stack = e.stack;error.name = e.name;}postMessage({type: 'RPC',id: id,error: error});});}});postMessage({type: 'RPC',method: 'ready'}); + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +var g; // This works in non-strict mode + +g = function () { + return this; +}(); + +try { + // This works if eval is allowed (see CSP) + g = g || new Function("return this")(); +} catch (e) { + // This works if the window reference is available + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object") g = window; +} // g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + + +module.exports = g; + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * cssfilter + * + * @author 老雷 + */ +var DEFAULT = __webpack_require__(4); + +var parseStyle = __webpack_require__(11); + +var _ = __webpack_require__(5); +/** + * 返回值是否为空 + * + * @param {Object} obj + * @return {Boolean} + */ + + +function isNull(obj) { + return obj === undefined || obj === null; +} +/** + * 浅拷贝对象 + * + * @param {Object} obj + * @return {Object} + */ + + +function shallowCopyObject(obj) { + var ret = {}; + + for (var i in obj) { + ret[i] = obj[i]; + } + + return ret; +} +/** + * 创建CSS过滤器 + * + * @param {Object} options + * - {Object} whiteList + * - {Function} onAttr + * - {Function} onIgnoreAttr + * - {Function} safeAttrValue + */ + + +function FilterCSS(options) { + options = shallowCopyObject(options || {}); + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onAttr = options.onAttr || DEFAULT.onAttr; + options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT.onIgnoreAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + this.options = options; +} + +FilterCSS.prototype.process = function (css) { + // 兼容各种奇葩输入 + css = css || ''; + css = css.toString(); + if (!css) return ''; + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onAttr = options.onAttr; + var onIgnoreAttr = options.onIgnoreAttr; + var safeAttrValue = options.safeAttrValue; + var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) { + var check = whiteList[name]; + var isWhite = false; + if (check === true) isWhite = check;else if (typeof check === 'function') isWhite = check(value);else if (check instanceof RegExp) isWhite = check.test(value); + if (isWhite !== true) isWhite = false; // 如果过滤后 value 为空则直接忽略 + + value = safeAttrValue(name, value); + if (!value) return; + var opts = { + position: position, + sourcePosition: sourcePosition, + source: source, + isWhite: isWhite + }; + + if (isWhite) { + var ret = onAttr(name, value, opts); + + if (isNull(ret)) { + return name + ':' + value; + } else { + return ret; + } + } else { + var ret = onIgnoreAttr(name, value, opts); + + if (!isNull(ret)) { + return ret; + } + } + }); + return retCSS; +}; + +module.exports = FilterCSS; + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * cssfilter + * + * @author 老雷 + */ +var _ = __webpack_require__(5); +/** + * 解析style + * + * @param {String} css + * @param {Function} onAttr 处理属性的函数 + * 参数格式: function (sourcePosition, position, name, value, source) + * @return {String} + */ + + +function parseStyle(css, onAttr) { + css = _.trimRight(css); + if (css[css.length - 1] !== ';') css += ';'; + var cssLength = css.length; + var isParenthesisOpen = false; + var lastPos = 0; + var i = 0; + var retCSS = ''; + + function addNewAttr() { + // 如果没有正常的闭合圆括号,则直接忽略当前属性 + if (!isParenthesisOpen) { + var source = _.trim(css.slice(lastPos, i)); + + var j = source.indexOf(':'); + + if (j !== -1) { + var name = _.trim(source.slice(0, j)); + + var value = _.trim(source.slice(j + 1)); // 必须有属性名称 + + + if (name) { + var ret = onAttr(lastPos, retCSS.length, name, value, source); + if (ret) retCSS += ret + '; '; + } + } + } + + lastPos = i + 1; + } + + for (; i < cssLength; i++) { + var c = css[i]; + + if (c === '/' && css[i + 1] === '*') { + // 备注开始 + var j = css.indexOf('*/', i + 2); // 如果没有正常的备注结束,则后面的部分全部跳过 + + if (j === -1) break; // 直接将当前位置调到备注结尾,并且初始化状态 + + i = j + 1; + lastPos = i + 1; + isParenthesisOpen = false; + } else if (c === '(') { + isParenthesisOpen = true; + } else if (c === ')') { + isParenthesisOpen = false; + } else if (c === ';') { + if (isParenthesisOpen) {// 在圆括号里面,忽略 + } else { + addNewAttr(); + } + } else if (c === '\n') { + addNewAttr(); + } + } + + return _.trim(retCSS); +} + +module.exports = parseStyle; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * filter xss + * + * @author Zongmin Lei + */ +var FilterCSS = __webpack_require__(0).FilterCSS; + +var DEFAULT = __webpack_require__(3); + +var parser = __webpack_require__(6); + +var parseTag = parser.parseTag; +var parseAttr = parser.parseAttr; + +var _ = __webpack_require__(1); +/** + * returns `true` if the input value is `undefined` or `null` + * + * @param {Object} obj + * @return {Boolean} + */ + + +function isNull(obj) { + return obj === undefined || obj === null; +} +/** + * get attributes for a tag + * + * @param {String} html + * @return {Object} + * - {String} html + * - {Boolean} closing + */ + + +function getAttrs(html) { + var i = _.spaceIndex(html); + + if (i === -1) { + return { + html: "", + closing: html[html.length - 2] === "/" + }; + } + + html = _.trim(html.slice(i + 1, -1)); + var isClosing = html[html.length - 1] === "/"; + if (isClosing) html = _.trim(html.slice(0, -1)); + return { + html: html, + closing: isClosing + }; +} +/** + * shallow copy + * + * @param {Object} obj + * @return {Object} + */ + + +function shallowCopyObject(obj) { + var ret = {}; + + for (var i in obj) { + ret[i] = obj[i]; + } + + return ret; +} +/** + * FilterXSS class + * + * @param {Object} options + * whiteList, onTag, onTagAttr, onIgnoreTag, + * onIgnoreTagAttr, safeAttrValue, escapeHtml + * stripIgnoreTagBody, allowCommentTag, stripBlankChar + * css{whiteList, onAttr, onIgnoreAttr} `css=false` means don't use `cssfilter` + */ + + +function FilterXSS(options) { + options = shallowCopyObject(options || {}); + + if (options.stripIgnoreTag) { + if (options.onIgnoreTag) { + console.error('Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'); + } + + options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll; + } + + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onTag = options.onTag || DEFAULT.onTag; + options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr; + options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag; + options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml; + this.options = options; + + if (options.css === false) { + this.cssFilter = false; + } else { + options.css = options.css || {}; + this.cssFilter = new FilterCSS(options.css); + } +} +/** + * start process and returns result + * + * @param {String} html + * @return {String} + */ + + +FilterXSS.prototype.process = function (html) { + // compatible with the input + html = html || ""; + html = html.toString(); + if (!html) return ""; + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onTag = options.onTag; + var onIgnoreTag = options.onIgnoreTag; + var onTagAttr = options.onTagAttr; + var onIgnoreTagAttr = options.onIgnoreTagAttr; + var safeAttrValue = options.safeAttrValue; + var escapeHtml = options.escapeHtml; + var cssFilter = me.cssFilter; // remove invisible characters + + if (options.stripBlankChar) { + html = DEFAULT.stripBlankChar(html); + } // remove html comments + + + if (!options.allowCommentTag) { + html = DEFAULT.stripCommentTag(html); + } // if enable stripIgnoreTagBody + + + var stripIgnoreTagBody = false; + + if (options.stripIgnoreTagBody) { + var stripIgnoreTagBody = DEFAULT.StripTagBody(options.stripIgnoreTagBody, onIgnoreTag); + onIgnoreTag = stripIgnoreTagBody.onIgnoreTag; + } + + var retHtml = parseTag(html, function (sourcePosition, position, tag, html, isClosing) { + var info = { + sourcePosition: sourcePosition, + position: position, + isClosing: isClosing, + isWhite: whiteList.hasOwnProperty(tag) + }; // call `onTag()` + + var ret = onTag(tag, html, info); + if (!isNull(ret)) return ret; + + if (info.isWhite) { + if (info.isClosing) { + return ""; + } + + var attrs = getAttrs(html); + var whiteAttrList = whiteList[tag]; + var attrsHtml = parseAttr(attrs.html, function (name, value) { + // call `onTagAttr()` + var isWhiteAttr = _.indexOf(whiteAttrList, name) !== -1; + var ret = onTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + + if (isWhiteAttr) { + // call `safeAttrValue()` + value = safeAttrValue(tag, name, value, cssFilter); + + if (value) { + return name + '="' + value + '"'; + } else { + return name; + } + } else { + // call `onIgnoreTagAttr()` + var ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + return; + } + }); // build new tag html + + var html = "<" + tag; + if (attrsHtml) html += " " + attrsHtml; + if (attrs.closing) html += " /"; + html += ">"; + return html; + } else { + // call `onIgnoreTag()` + var ret = onIgnoreTag(tag, html, info); + if (!isNull(ret)) return ret; + return escapeHtml(html); + } + }, escapeHtml); // if enable stripIgnoreTagBody + + if (stripIgnoreTagBody) { + retHtml = stripIgnoreTagBody.remove(retHtml); + } + + return retHtml; +}; + +module.exports = FilterXSS; + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/supervisor/api/panel/7e78115f8d410990252b.worker.js.gz b/supervisor/api/panel/7e78115f8d410990252b.worker.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..7e7d3afdf3c3ad723c74fe33bdbe86858702c2f8 GIT binary patch literal 22678 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 VHWT%S{-(&z-vE3eO5b#g0RXC8Z%hCH literal 0 HcmV?d00001 diff --git a/supervisor/api/panel/chunk.066811ee56df2879fa62.js b/supervisor/api/panel/chunk.066811ee56df2879fa62.js new file mode 100644 index 000000000..248edaac8 --- /dev/null +++ b/supervisor/api/panel/chunk.066811ee56df2879fa62.js @@ -0,0 +1,14894 @@ +(self["webpackJsonp"] = self["webpackJsonp"] || []).push([[10],{ + +/***/ 181: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ("/* BASICS */\n\n.CodeMirror {\n /* Set height, width, borders, and global font properties here */\n font-family: monospace;\n height: 300px;\n color: black;\n direction: ltr;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre.CodeMirror-line,\n.CodeMirror pre.CodeMirror-line-like {\n padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n border-right: 1px solid #ddd;\n background-color: #f7f7f7;\n white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n padding: 0 3px 0 5px;\n min-width: 20px;\n text-align: right;\n color: #999;\n white-space: nowrap;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n border-left: 1px solid black;\n border-right: none;\n width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n width: auto;\n border: 0 !important;\n background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n z-index: 1;\n}\n.cm-fat-cursor-mark {\n background-color: rgba(20, 255, 20, 0.5);\n -webkit-animation: blink 1.06s steps(1) infinite;\n -moz-animation: blink 1.06s steps(1) infinite;\n animation: blink 1.06s steps(1) infinite;\n}\n.cm-animate-fat-cursor {\n width: auto;\n border: 0;\n -webkit-animation: blink 1.06s steps(1) infinite;\n -moz-animation: blink 1.06s steps(1) infinite;\n animation: blink 1.06s steps(1) infinite;\n background-color: #7e7;\n}\n@-moz-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@-webkit-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-rulers {\n position: absolute;\n left: 0; right: 0; top: -50px; bottom: 0;\n overflow: hidden;\n}\n.CodeMirror-ruler {\n border-left: 1px solid #ccc;\n top: 0; bottom: 0;\n position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n position: relative;\n overflow: hidden;\n background: white;\n}\n\n.CodeMirror-scroll {\n overflow: scroll !important; /* Things will break if this is overridden */\n /* 30px is the magic margin used to hide the element's real scrollbars */\n /* See overflow: hidden in .CodeMirror */\n margin-bottom: -30px; margin-right: -30px;\n padding-bottom: 30px;\n height: 100%;\n outline: none; /* Prevent dragging from highlighting the element */\n position: relative;\n}\n.CodeMirror-sizer {\n position: relative;\n border-right: 30px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n before actual scrolling happens, thus preventing shaking and\n flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n position: absolute;\n z-index: 6;\n display: none;\n}\n.CodeMirror-vscrollbar {\n right: 0; top: 0;\n overflow-x: hidden;\n overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n bottom: 0; left: 0;\n overflow-y: hidden;\n overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n position: absolute; left: 0; top: 0;\n min-height: 100%;\n z-index: 3;\n}\n.CodeMirror-gutter {\n white-space: normal;\n height: 100%;\n display: inline-block;\n vertical-align: top;\n margin-bottom: -30px;\n}\n.CodeMirror-gutter-wrapper {\n position: absolute;\n z-index: 4;\n background: none !important;\n border: none !important;\n}\n.CodeMirror-gutter-background {\n position: absolute;\n top: 0; bottom: 0;\n z-index: 4;\n}\n.CodeMirror-gutter-elt {\n position: absolute;\n cursor: default;\n z-index: 4;\n}\n.CodeMirror-gutter-wrapper ::selection { background-color: transparent }\n.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }\n\n.CodeMirror-lines {\n cursor: text;\n min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre.CodeMirror-line,\n.CodeMirror pre.CodeMirror-line-like {\n /* Reset some styles that the rest of the page might have set */\n -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n border-width: 0;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n margin: 0;\n white-space: pre;\n word-wrap: normal;\n line-height: inherit;\n color: inherit;\n z-index: 2;\n position: relative;\n overflow: visible;\n -webkit-tap-highlight-color: transparent;\n -webkit-font-variant-ligatures: contextual;\n font-variant-ligatures: contextual;\n}\n.CodeMirror-wrap pre.CodeMirror-line,\n.CodeMirror-wrap pre.CodeMirror-line-like {\n word-wrap: break-word;\n white-space: pre-wrap;\n word-break: normal;\n}\n\n.CodeMirror-linebackground {\n position: absolute;\n left: 0; right: 0; top: 0; bottom: 0;\n z-index: 0;\n}\n\n.CodeMirror-linewidget {\n position: relative;\n z-index: 2;\n padding: 0.1px; /* Force widget margins to stay inside of the container */\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-rtl pre { direction: rtl; }\n\n.CodeMirror-code {\n outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n position: absolute;\n width: 100%;\n height: 0;\n overflow: hidden;\n visibility: hidden;\n}\n\n.CodeMirror-cursor {\n position: absolute;\n pointer-events: none;\n}\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n visibility: hidden;\n position: relative;\n z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n background-color: #ffa;\n background-color: rgba(255, 255, 0, .4);\n}\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n /* Hide the cursor when printing */\n .CodeMirror div.CodeMirror-cursors {\n visibility: hidden;\n }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"); + +/***/ }), + +/***/ 182: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE +(function (mod) { + if (( false ? undefined : _typeof(exports)) == "object" && ( false ? undefined : _typeof(module)) == "object") // CommonJS + mod(__webpack_require__(54));else if (true) // AMD + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(54)], __WEBPACK_AMD_DEFINE_FACTORY__ = (mod), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else // Plain browser env + {} +})(function (CodeMirror) { + "use strict"; + + CodeMirror.defineMode("jinja2", function () { + var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif", "extends", "filter", "endfilter", "firstof", "for", "endfor", "if", "endif", "ifchanged", "endifchanged", "ifequal", "endifequal", "ifnotequal", "endifnotequal", "in", "include", "load", "not", "now", "or", "parsed", "regroup", "reversed", "spaceless", "endspaceless", "ssi", "templatetag", "openblock", "closeblock", "openvariable", "closevariable", "openbrace", "closebrace", "opencomment", "closecomment", "widthratio", "url", "with", "endwith", "get_current_language", "trans", "endtrans", "noop", "blocktrans", "endblocktrans", "get_available_languages", "get_current_language_bidi", "plural"], + operator = /^[+\-*&%=<>!?|~^]/, + sign = /^[:\[\(\{]/, + atom = ["true", "false"], + number = /^(\d[+\-\*\/])?\d+(\.\d+)?/; + keywords = new RegExp("((" + keywords.join(")|(") + "))\\b"); + atom = new RegExp("((" + atom.join(")|(") + "))\\b"); + + function tokenBase(stream, state) { + var ch = stream.peek(); //Comment + + if (state.incomment) { + if (!stream.skipTo("#}")) { + stream.skipToEnd(); + } else { + stream.eatWhile(/\#|}/); + state.incomment = false; + } + + return "comment"; //Tag + } else if (state.intag) { + //After operator + if (state.operator) { + state.operator = false; + + if (stream.match(atom)) { + return "atom"; + } + + if (stream.match(number)) { + return "number"; + } + } //After sign + + + if (state.sign) { + state.sign = false; + + if (stream.match(atom)) { + return "atom"; + } + + if (stream.match(number)) { + return "number"; + } + } + + if (state.instring) { + if (ch == state.instring) { + state.instring = false; + } + + stream.next(); + return "string"; + } else if (ch == "'" || ch == '"') { + state.instring = ch; + stream.next(); + return "string"; + } else if (stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) { + state.intag = false; + return "tag"; + } else if (stream.match(operator)) { + state.operator = true; + return "operator"; + } else if (stream.match(sign)) { + state.sign = true; + } else { + if (stream.eat(" ") || stream.sol()) { + if (stream.match(keywords)) { + return "keyword"; + } + + if (stream.match(atom)) { + return "atom"; + } + + if (stream.match(number)) { + return "number"; + } + + if (stream.sol()) { + stream.next(); + } + } else { + stream.next(); + } + } + + return "variable"; + } else if (stream.eat("{")) { + if (stream.eat("#")) { + state.incomment = true; + + if (!stream.skipTo("#}")) { + stream.skipToEnd(); + } else { + stream.eatWhile(/\#|}/); + state.incomment = false; + } + + return "comment"; //Open tag + } else if (ch = stream.eat(/\{|%/)) { + //Cache close tag + state.intag = ch; + + if (ch == "{") { + state.intag = "}"; + } + + stream.eat("-"); + return "tag"; + } + } + + stream.next(); + } + + ; + return { + startState: function startState() { + return { + tokenize: tokenBase + }; + }, + token: function token(stream, state) { + return state.tokenize(stream, state); + }, + blockCommentStart: "{#", + blockCommentEnd: "#}" + }; + }); + CodeMirror.defineMIME("text/jinja2", "jinja2"); +}); +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(92)(module))) + +/***/ }), + +/***/ 183: +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE +(function (mod) { + if (( false ? undefined : _typeof(exports)) == "object" && ( false ? undefined : _typeof(module)) == "object") // CommonJS + mod(__webpack_require__(54));else if (true) // AMD + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(54)], __WEBPACK_AMD_DEFINE_FACTORY__ = (mod), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else // Plain browser env + {} +})(function (CodeMirror) { + "use strict"; + + CodeMirror.defineMode("yaml", function () { + var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; + var keywordRegex = new RegExp("\\b((" + cons.join(")|(") + "))$", 'i'); + return { + token: function token(stream, state) { + var ch = stream.peek(); + var esc = state.escaped; + state.escaped = false; + /* comments */ + + if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) { + stream.skipToEnd(); + return "comment"; + } + + if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/)) return "string"; + + if (state.literal && stream.indentation() > state.keyCol) { + stream.skipToEnd(); + return "string"; + } else if (state.literal) { + state.literal = false; + } + + if (stream.sol()) { + state.keyCol = 0; + state.pair = false; + state.pairStart = false; + /* document start */ + + if (stream.match(/---/)) { + return "def"; + } + /* document end */ + + + if (stream.match(/\.\.\./)) { + return "def"; + } + /* array list item */ + + + if (stream.match(/\s*-\s+/)) { + return 'meta'; + } + } + /* inline pairs/lists */ + + + if (stream.match(/^(\{|\}|\[|\])/)) { + if (ch == '{') state.inlinePairs++;else if (ch == '}') state.inlinePairs--;else if (ch == '[') state.inlineList++;else state.inlineList--; + return 'meta'; + } + /* list seperator */ + + + if (state.inlineList > 0 && !esc && ch == ',') { + stream.next(); + return 'meta'; + } + /* pairs seperator */ + + + if (state.inlinePairs > 0 && !esc && ch == ',') { + state.keyCol = 0; + state.pair = false; + state.pairStart = false; + stream.next(); + return 'meta'; + } + /* start of value of a pair */ + + + if (state.pairStart) { + /* block literals */ + if (stream.match(/^\s*(\||\>)\s*/)) { + state.literal = true; + return 'meta'; + } + + ; + /* references */ + + if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { + return 'variable-2'; + } + /* numbers */ + + + if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { + return 'number'; + } + + if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { + return 'number'; + } + /* keywords */ + + + if (stream.match(keywordRegex)) { + return 'keyword'; + } + } + /* pairs (associative arrays) -> key */ + + + if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) { + state.pair = true; + state.keyCol = stream.indentation(); + return "atom"; + } + + if (state.pair && stream.match(/^:\s*/)) { + state.pairStart = true; + return 'meta'; + } + /* nothing found, continue */ + + + state.pairStart = false; + state.escaped = ch == '\\'; + stream.next(); + return null; + }, + startState: function startState() { + return { + pair: false, + pairStart: false, + keyCol: 0, + inlinePairs: 0, + inlineList: 0, + literal: false, + escaped: false + }; + }, + lineComment: "#", + fold: "indent" + }; + }); + CodeMirror.defineMIME("text/x-yaml", "yaml"); + CodeMirror.defineMIME("text/yaml", "yaml"); +}); +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(92)(module))) + +/***/ }), + +/***/ 54: +/***/ (function(module, exports, __webpack_require__) { + +var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE +// This is CodeMirror (https://codemirror.net), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . +(function (global, factory) { + ( false ? undefined : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : + __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : undefined; +})(this, function () { + 'use strict'; // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + + var userAgent = navigator.userAgent; + var platform = navigator.platform; + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var edge = /Edge\/(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up || edge; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); + var webkit = !edge && /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = !edge && /Chrome\//.test(userAgent); + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); + var android = /Android/.test(userAgent); // This is woefully incomplete. Suggestions for alternative methods welcome. + + var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + + if (presto_version) { + presto_version = Number(presto_version[1]); + } + + if (presto_version && presto_version >= 15) { + presto = false; + webkit = true; + } // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + + + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || ie && ie_version >= 9; + + function classTest(cls) { + return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); + } + + var rmClass = function rmClass(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) { + e.removeChild(e.firstChild); + } + + return e; + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e); + } + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + + if (className) { + e.className = className; + } + + if (style) { + e.style.cssText = style; + } + + if (typeof content == "string") { + e.appendChild(document.createTextNode(content)); + } else if (content) { + for (var i = 0; i < content.length; ++i) { + e.appendChild(content[i]); + } + } + + return e; + } // wrapper for elt, which removes the elt from the accessibility tree + + + function eltP(tag, content, className, style) { + var e = elt(tag, content, className, style); + e.setAttribute("role", "presentation"); + return e; + } + + var range; + + if (document.createRange) { + range = function range(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r; + }; + } else { + range = function range(node, start, end) { + var r = document.body.createTextRange(); + + try { + r.moveToElementText(node.parentNode); + } catch (e) { + return r; + } + + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r; + }; + } + + function contains(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + { + child = child.parentNode; + } + + if (parent.contains) { + return parent.contains(child); + } + + do { + if (child.nodeType == 11) { + child = child.host; + } + + if (child == parent) { + return true; + } + } while (child = child.parentNode); + } + + function activeElt() { + // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. + // IE < 10 will throw when accessed while the page is loading or in an iframe. + // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. + var activeElement; + + try { + activeElement = document.activeElement; + } catch (e) { + activeElement = document.body || null; + } + + while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) { + activeElement = activeElement.shadowRoot.activeElement; + } + + return activeElement; + } + + function addClass(node, cls) { + var current = node.className; + + if (!classTest(cls).test(current)) { + node.className += (current ? " " : "") + cls; + } + } + + function joinClasses(a, b) { + var as = a.split(" "); + + for (var i = 0; i < as.length; i++) { + if (as[i] && !classTest(as[i]).test(b)) { + b += " " + as[i]; + } + } + + return b; + } + + var selectInput = function selectInput(node) { + node.select(); + }; + + if (ios) // Mobile Safari apparently has a bug where select() is broken. + { + selectInput = function selectInput(node) { + node.selectionStart = 0; + node.selectionEnd = node.value.length; + }; + } else if (ie) // Suppress mysterious IE10 errors + { + selectInput = function selectInput(node) { + try { + node.select(); + } catch (_e) {} + }; + } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return f.apply(null, args); + }; + } + + function copyObj(obj, target, overwrite) { + if (!target) { + target = {}; + } + + for (var prop in obj) { + if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) { + target[prop] = obj[prop]; + } + } + + return target; + } // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + + + function countColumn(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + + if (end == -1) { + end = string.length; + } + } + + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + + if (nextTab < 0 || nextTab >= end) { + return n + (end - i); + } + + n += nextTab - i; + n += tabSize - n % tabSize; + i = nextTab + 1; + } + } + + var Delayed = function Delayed() { + this.id = null; + }; + + Delayed.prototype.set = function (ms, f) { + clearTimeout(this.id); + this.id = setTimeout(f, ms); + }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) { + if (array[i] == elt) { + return i; + } + } + + return -1; + } // Number of pixels added to scroller and sizer to hide scrollbar + + + var scrollerGap = 30; // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + + var Pass = { + toString: function toString() { + return "CodeMirror.Pass"; + } + }; // Reused option objects for setSelection & friends + + var sel_dontScroll = { + scroll: false + }, + sel_mouse = { + origin: "*mouse" + }, + sel_move = { + origin: "+move" + }; // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + + function findColumn(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + + if (nextTab == -1) { + nextTab = string.length; + } + + var skipped = nextTab - pos; + + if (nextTab == string.length || col + skipped >= goal) { + return pos + Math.min(skipped, goal - col); + } + + col += nextTab - pos; + col += tabSize - col % tabSize; + pos = nextTab + 1; + + if (col >= goal) { + return pos; + } + } + } + + var spaceStrs = [""]; + + function spaceStr(n) { + while (spaceStrs.length <= n) { + spaceStrs.push(lst(spaceStrs) + " "); + } + + return spaceStrs[n]; + } + + function lst(arr) { + return arr[arr.length - 1]; + } + + function map(array, f) { + var out = []; + + for (var i = 0; i < array.length; i++) { + out[i] = f(array[i], i); + } + + return out; + } + + function insertSorted(array, value, score) { + var pos = 0, + priority = score(value); + + while (pos < array.length && score(array[pos]) <= priority) { + pos++; + } + + array.splice(pos, 0, value); + } + + function nothing() {} + + function createObj(base, props) { + var inst; + + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + + if (props) { + copyObj(props, inst); + } + + return inst; + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + + function isWordCharBasic(ch) { + return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + } + + function isWordChar(ch, helper) { + if (!helper) { + return isWordCharBasic(ch); + } + + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { + return true; + } + + return helper.test(ch); + } + + function isEmpty(obj) { + for (var n in obj) { + if (obj.hasOwnProperty(n) && obj[n]) { + return false; + } + } + + return true; + } // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + + + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + + function isExtendingChar(ch) { + return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); + } // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. + + + function skipExtendingChars(str, pos, dir) { + while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { + pos += dir; + } + + return pos; + } // Returns the value from the range [`from`; `to`] that satisfies + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. + + + function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1; + + for (;;) { + if (from == to) { + return from; + } + + var midF = (from + to) / 2, + mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); + + if (mid == from) { + return pred(mid) ? from : to; + } + + if (pred(mid)) { + to = mid; + } else { + from = mid + dir; + } + } + } // BIDI HELPERS + + + function iterateBidiSections(order, from, to, f) { + if (!order) { + return f(from, to, "ltr", 0); + } + + var found = false; + + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); + found = true; + } + } + + if (!found) { + f(from, to, "ltr"); + } + } + + var bidiOther = null; + + function getBidiPartAt(order, ch, sticky) { + var found; + bidiOther = null; + + for (var i = 0; i < order.length; ++i) { + var cur = order[i]; + + if (cur.from < ch && cur.to > ch) { + return i; + } + + if (cur.to == ch) { + if (cur.from != cur.to && sticky == "before") { + found = i; + } else { + bidiOther = i; + } + } + + if (cur.from == ch) { + if (cur.from != cur.to && sticky != "before") { + found = i; + } else { + bidiOther = i; + } + } + } + + return found != null ? found : bidiOther; + } // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + + + var bidiOrdering = function () { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; // Character types for codepoints 0x600 to 0x6f9 + + var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; + + function charType(code) { + if (code <= 0xf7) { + return lowTypes.charAt(code); + } else if (0x590 <= code && code <= 0x5f4) { + return "R"; + } else if (0x600 <= code && code <= 0x6f9) { + return arabicTypes.charAt(code - 0x600); + } else if (0x6ee <= code && code <= 0x8ac) { + return "r"; + } else if (0x2000 <= code && code <= 0x200b) { + return "w"; + } else if (code == 0x200c) { + return "b"; + } else { + return "L"; + } + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, + isStrong = /[LRr]/, + countsAsLeft = /[Lb1n]/, + countsAsNum = /[1n]/; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; + this.to = to; + } + + return function (str, direction) { + var outerType = direction == "ltr" ? "L" : "R"; + + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { + return false; + } + + var len = str.length, + types = []; + + for (var i = 0; i < len; ++i) { + types.push(charType(str.charCodeAt(i))); + } // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + + + for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { + var type = types[i$1]; + + if (type == "m") { + types[i$1] = prev; + } else { + prev = type; + } + } // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + + + for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { + var type$1 = types[i$2]; + + if (type$1 == "1" && cur == "r") { + types[i$2] = "n"; + } else if (isStrong.test(type$1)) { + cur = type$1; + + if (type$1 == "r") { + types[i$2] = "R"; + } + } + } // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + + + for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { + var type$2 = types[i$3]; + + if (type$2 == "+" && prev$1 == "1" && types[i$3 + 1] == "1") { + types[i$3] = "1"; + } else if (type$2 == "," && prev$1 == types[i$3 + 1] && (prev$1 == "1" || prev$1 == "n")) { + types[i$3] = prev$1; + } + + prev$1 = type$2; + } // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + + + for (var i$4 = 0; i$4 < len; ++i$4) { + var type$3 = types[i$4]; + + if (type$3 == ",") { + types[i$4] = "N"; + } else if (type$3 == "%") { + var end = void 0; + + for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} + + var replace = i$4 && types[i$4 - 1] == "!" || end < len && types[end] == "1" ? "1" : "N"; + + for (var j = i$4; j < end; ++j) { + types[j] = replace; + } + + i$4 = end - 1; + } + } // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + + + for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { + var type$4 = types[i$5]; + + if (cur$1 == "L" && type$4 == "1") { + types[i$5] = "L"; + } else if (isStrong.test(type$4)) { + cur$1 = type$4; + } + } // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + + + for (var i$6 = 0; i$6 < len; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = void 0; + + for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} + + var before = (i$6 ? types[i$6 - 1] : outerType) == "L"; + var after = (end$1 < len ? types[end$1] : outerType) == "L"; + var replace$1 = before == after ? before ? "L" : "R" : outerType; + + for (var j$1 = i$6; j$1 < end$1; ++j$1) { + types[j$1] = replace$1; + } + + i$6 = end$1 - 1; + } + } // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + + + var order = [], + m; + + for (var i$7 = 0; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7; + + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + + order.push(new BidiSpan(0, start, i$7)); + } else { + var pos = i$7, + at = order.length; + + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { + order.splice(at, 0, new BidiSpan(1, pos, j$2)); + } + + var nstart = j$2; + + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + + order.splice(at, 0, new BidiSpan(2, nstart, j$2)); + pos = j$2; + } else { + ++j$2; + } + } + + if (pos < i$7) { + order.splice(at, 0, new BidiSpan(1, pos, i$7)); + } + } + } + + if (direction == "ltr") { + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + } + + return direction == "rtl" ? order.reverse() : order; + }; + }(); // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + + + function getOrder(line, direction) { + var order = line.order; + + if (order == null) { + order = line.order = bidiOrdering(line.text, direction); + } + + return order; + } // EVENT HANDLING + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + + var noHandlers = []; + + var on = function on(emitter, type, f) { + if (emitter.addEventListener) { + emitter.addEventListener(type, f, false); + } else if (emitter.attachEvent) { + emitter.attachEvent("on" + type, f); + } else { + var map$$1 = emitter._handlers || (emitter._handlers = {}); + map$$1[type] = (map$$1[type] || noHandlers).concat(f); + } + }; + + function getHandlers(emitter, type) { + return emitter._handlers && emitter._handlers[type] || noHandlers; + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) { + emitter.removeEventListener(type, f, false); + } else if (emitter.detachEvent) { + emitter.detachEvent("on" + type, f); + } else { + var map$$1 = emitter._handlers, + arr = map$$1 && map$$1[type]; + + if (arr) { + var index = indexOf(arr, f); + + if (index > -1) { + map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); + } + } + } + } + + function signal(emitter, type + /*, values...*/ + ) { + var handlers = getHandlers(emitter, type); + + if (!handlers.length) { + return; + } + + var args = Array.prototype.slice.call(arguments, 2); + + for (var i = 0; i < handlers.length; ++i) { + handlers[i].apply(null, args); + } + } // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + + + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") { + e = { + type: e, + preventDefault: function preventDefault() { + this.defaultPrevented = true; + } + }; + } + + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore; + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + + if (!arr) { + return; + } + + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + + for (var i = 0; i < arr.length; ++i) { + if (indexOf(set, arr[i]) == -1) { + set.push(arr[i]); + } + } + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0; + } // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + + + function eventMixin(ctor) { + ctor.prototype.on = function (type, f) { + on(this, type, f); + }; + + ctor.prototype.off = function (type, f) { + off(this, type, f); + }; + } // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + + function e_preventDefault(e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + } + + function e_stopPropagation(e) { + if (e.stopPropagation) { + e.stopPropagation(); + } else { + e.cancelBubble = true; + } + } + + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; + } + + function e_stop(e) { + e_preventDefault(e); + e_stopPropagation(e); + } + + function e_target(e) { + return e.target || e.srcElement; + } + + function e_button(e) { + var b = e.which; + + if (b == null) { + if (e.button & 1) { + b = 1; + } else if (e.button & 2) { + b = 3; + } else if (e.button & 4) { + b = 2; + } + } + + if (mac && e.ctrlKey && b == 1) { + b = 3; + } + + return b; + } // Detect drag-and-drop + + + var dragAndDrop = function () { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) { + return false; + } + + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + var zwspSupported; + + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200B"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + + if (measure.firstChild.offsetHeight != 0) { + zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); + } + } + + var node = zwspSupported ? elt("span", "\u200B") : elt("span", "\xA0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node; + } // Feature-detect IE's crummy client rect reporting for bidi text + + + var badBidiRects; + + function hasBadBidiRects(measure) { + if (badBidiRects != null) { + return badBidiRects; + } + + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062EA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + + if (!r0 || r0.left == r0.right) { + return false; + } // Safari returns null in some cases (#2780) + + + return badBidiRects = r1.right - r0.right < 3; + } // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + + + var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { + var pos = 0, + result = [], + l = string.length; + + while (pos <= l) { + var nl = string.indexOf("\n", pos); + + if (nl == -1) { + nl = string.length; + } + + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + + return result; + } : function (string) { + return string.split(/\r\n?|\n/); + }; + var hasSelection = window.getSelection ? function (te) { + try { + return te.selectionStart != te.selectionEnd; + } catch (e) { + return false; + } + } : function (te) { + var range$$1; + + try { + range$$1 = te.ownerDocument.selection.createRange(); + } catch (e) {} + + if (!range$$1 || range$$1.parentElement() != te) { + return false; + } + + return range$$1.compareEndPoints("StartToEnd", range$$1) != 0; + }; + + var hasCopyEvent = function () { + var e = elt("div"); + + if ("oncopy" in e) { + return true; + } + + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function"; + }(); + + var badZoomedRects = null; + + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) { + return badZoomedRects; + } + + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; + } // Known modes, by name and by MIME + + + var modes = {}, + mimeModes = {}; // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + + function defineMode(name, mode) { + if (arguments.length > 2) { + mode.dependencies = Array.prototype.slice.call(arguments, 2); + } + + modes[name] = mode; + } + + function defineMIME(mime, spec) { + mimeModes[mime] = spec; + } // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + + + function resolveMode(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + + if (typeof found == "string") { + found = { + name: found + }; + } + + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return resolveMode("application/xml"); + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return resolveMode("application/json"); + } + + if (typeof spec == "string") { + return { + name: spec + }; + } else { + return spec || { + name: "null" + }; + } + } // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + + + function getMode(options, spec) { + spec = resolveMode(spec); + var mfactory = modes[spec.name]; + + if (!mfactory) { + return getMode(options, "text/plain"); + } + + var modeObj = mfactory(options, spec); + + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) { + continue; + } + + if (modeObj.hasOwnProperty(prop)) { + modeObj["_" + prop] = modeObj[prop]; + } + + modeObj[prop] = exts[prop]; + } + } + + modeObj.name = spec.name; + + if (spec.helperType) { + modeObj.helperType = spec.helperType; + } + + if (spec.modeProps) { + for (var prop$1 in spec.modeProps) { + modeObj[prop$1] = spec.modeProps[prop$1]; + } + } + + return modeObj; + } // This can be used to attach properties to mode objects from + // outside the actual mode definition. + + + var modeExtensions = {}; + + function extendMode(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : modeExtensions[mode] = {}; + copyObj(properties, exts); + } + + function copyState(mode, state) { + if (state === true) { + return state; + } + + if (mode.copyState) { + return mode.copyState(state); + } + + var nstate = {}; + + for (var n in state) { + var val = state[n]; + + if (val instanceof Array) { + val = val.concat([]); + } + + nstate[n] = val; + } + + return nstate; + } // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + + + function innerMode(mode, state) { + var info; + + while (mode.innerMode) { + info = mode.innerMode(state); + + if (!info || info.mode == mode) { + break; + } + + state = info.state; + mode = info.mode; + } + + return info || { + mode: mode, + state: state + }; + } + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + } // STRING STREAM + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + + var StringStream = function StringStream(string, tabSize, lineOracle) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + this.lineOracle = lineOracle; + }; + + StringStream.prototype.eol = function () { + return this.pos >= this.string.length; + }; + + StringStream.prototype.sol = function () { + return this.pos == this.lineStart; + }; + + StringStream.prototype.peek = function () { + return this.string.charAt(this.pos) || undefined; + }; + + StringStream.prototype.next = function () { + if (this.pos < this.string.length) { + return this.string.charAt(this.pos++); + } + }; + + StringStream.prototype.eat = function (match) { + var ch = this.string.charAt(this.pos); + var ok; + + if (typeof match == "string") { + ok = ch == match; + } else { + ok = ch && (match.test ? match.test(ch) : match(ch)); + } + + if (ok) { + ++this.pos; + return ch; + } + }; + + StringStream.prototype.eatWhile = function (match) { + var start = this.pos; + + while (this.eat(match)) {} + + return this.pos > start; + }; + + StringStream.prototype.eatSpace = function () { + var this$1 = this; + var start = this.pos; + + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { + ++this$1.pos; + } + + return this.pos > start; + }; + + StringStream.prototype.skipToEnd = function () { + this.pos = this.string.length; + }; + + StringStream.prototype.skipTo = function (ch) { + var found = this.string.indexOf(ch, this.pos); + + if (found > -1) { + this.pos = found; + return true; + } + }; + + StringStream.prototype.backUp = function (n) { + this.pos -= n; + }; + + StringStream.prototype.column = function () { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }; + + StringStream.prototype.indentation = function () { + return countColumn(this.string, null, this.tabSize) - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }; + + StringStream.prototype.match = function (pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function cased(str) { + return caseInsensitive ? str.toLowerCase() : str; + }; + + var substr = this.string.substr(this.pos, pattern.length); + + if (cased(substr) == cased(pattern)) { + if (consume !== false) { + this.pos += pattern.length; + } + + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + + if (match && match.index > 0) { + return null; + } + + if (match && consume !== false) { + this.pos += match[0].length; + } + + return match; + } + }; + + StringStream.prototype.current = function () { + return this.string.slice(this.start, this.pos); + }; + + StringStream.prototype.hideFirstChars = function (n, inner) { + this.lineStart += n; + + try { + return inner(); + } finally { + this.lineStart -= n; + } + }; + + StringStream.prototype.lookAhead = function (n) { + var oracle = this.lineOracle; + return oracle && oracle.lookAhead(n); + }; + + StringStream.prototype.baseToken = function () { + var oracle = this.lineOracle; + return oracle && oracle.baseToken(this.pos); + }; // Find the line object corresponding to the given line number. + + + function getLine(doc, n) { + n -= doc.first; + + if (n < 0 || n >= doc.size) { + throw new Error("There is no line " + (n + doc.first) + " in the document."); + } + + var chunk = doc; + + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], + sz = child.chunkSize(); + + if (n < sz) { + chunk = child; + break; + } + + n -= sz; + } + } + + return chunk.lines[n]; + } // Get the part of a document between two positions, as an array of + // strings. + + + function getBetween(doc, start, end) { + var out = [], + n = start.line; + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text; + + if (n == end.line) { + text = text.slice(0, end.ch); + } + + if (n == start.line) { + text = text.slice(start.ch); + } + + out.push(text); + ++n; + }); + return out; + } // Get the lines between from and to, as array of strings. + + + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function (line) { + out.push(line.text); + }); // iter aborts when callback returns truthy value + + return out; + } // Update the height of a line, propagating the height change + // upwards to parent nodes. + + + function updateLineHeight(line, height) { + var diff = height - line.height; + + if (diff) { + for (var n = line; n; n = n.parent) { + n.height += diff; + } + } + } // Given a line object, find its line number by walking up through + // its parent links. + + + function lineNo(line) { + if (line.parent == null) { + return null; + } + + var cur = line.parent, + no = indexOf(cur.lines, line); + + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { + break; + } + + no += chunk.children[i].chunkSize(); + } + } + + return no + cur.first; + } // Find the line at the given vertical position, using the height + // information in the document tree. + + + function _lineAtHeight(chunk, h) { + var n = chunk.first; + + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], + ch = child.height; + + if (h < ch) { + chunk = child; + continue outer; + } + + h -= ch; + n += child.chunkSize(); + } + + return n; + } while (!chunk.lines); + + var i = 0; + + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], + lh = line.height; + + if (h < lh) { + break; + } + + h -= lh; + } + + return n + i; + } + + function isLine(doc, l) { + return l >= doc.first && l < doc.first + doc.size; + } + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)); + } // A Pos instance represents a position within the text. + + + function Pos(line, ch, sticky) { + if (sticky === void 0) sticky = null; + + if (!(this instanceof Pos)) { + return new Pos(line, ch, sticky); + } + + this.line = line; + this.ch = ch; + this.sticky = sticky; + } // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + + + function cmp(a, b) { + return a.line - b.line || a.ch - b.ch; + } + + function equalCursorPos(a, b) { + return a.sticky == b.sticky && cmp(a, b) == 0; + } + + function copyPos(x) { + return Pos(x.line, x.ch); + } + + function maxPos(a, b) { + return cmp(a, b) < 0 ? b : a; + } + + function minPos(a, b) { + return cmp(a, b) < 0 ? a : b; + } // Most of the external API clips given positions to make sure they + // actually exist within the document. + + + function clipLine(doc, n) { + return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1)); + } + + function _clipPos(doc, pos) { + if (pos.line < doc.first) { + return Pos(doc.first, 0); + } + + var last = doc.first + doc.size - 1; + + if (pos.line > last) { + return Pos(last, getLine(doc, last).text.length); + } + + return clipToLen(pos, getLine(doc, pos.line).text.length); + } + + function clipToLen(pos, linelen) { + var ch = pos.ch; + + if (ch == null || ch > linelen) { + return Pos(pos.line, linelen); + } else if (ch < 0) { + return Pos(pos.line, 0); + } else { + return pos; + } + } + + function clipPosArray(doc, array) { + var out = []; + + for (var i = 0; i < array.length; i++) { + out[i] = _clipPos(doc, array[i]); + } + + return out; + } + + var SavedContext = function SavedContext(state, lookAhead) { + this.state = state; + this.lookAhead = lookAhead; + }; + + var Context = function Context(doc, state, line, lookAhead) { + this.state = state; + this.doc = doc; + this.line = line; + this.maxLookAhead = lookAhead || 0; + this.baseTokens = null; + this.baseTokenPos = 1; + }; + + Context.prototype.lookAhead = function (n) { + var line = this.doc.getLine(this.line + n); + + if (line != null && n > this.maxLookAhead) { + this.maxLookAhead = n; + } + + return line; + }; + + Context.prototype.baseToken = function (n) { + var this$1 = this; + + if (!this.baseTokens) { + return null; + } + + while (this.baseTokens[this.baseTokenPos] <= n) { + this$1.baseTokenPos += 2; + } + + var type = this.baseTokens[this.baseTokenPos + 1]; + return { + type: type && type.replace(/( |^)overlay .*/, ""), + size: this.baseTokens[this.baseTokenPos] - n + }; + }; + + Context.prototype.nextLine = function () { + this.line++; + + if (this.maxLookAhead > 0) { + this.maxLookAhead--; + } + }; + + Context.fromSaved = function (doc, saved, line) { + if (saved instanceof SavedContext) { + return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead); + } else { + return new Context(doc, copyState(doc.mode, saved), line); + } + }; + + Context.prototype.save = function (copy) { + var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; + return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state; + }; // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + + + function highlightLine(cm, line, context, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], + lineClasses = {}; // Compute the base array of styles + + runMode(cm, line.text, cm.doc.mode, context, function (end, style) { + return st.push(end, style); + }, lineClasses, forceToEnd); + var state = context.state; // Run overlays, adjust style array. + + var loop = function loop(o) { + context.baseTokens = st; + var overlay = cm.state.overlays[o], + i = 1, + at = 0; + context.state = true; + runMode(cm, line.text, overlay.mode, context, function (end, style) { + var start = i; // Ensure there's a token end at the current position, and that i points at it + + while (at < end) { + var i_end = st[i]; + + if (i_end > end) { + st.splice(i, 1, end, st[i + 1], i_end); + } + + i += 2; + at = Math.min(end, i_end); + } + + if (!style) { + return; + } + + if (overlay.opaque) { + st.splice(start, i - start, end, "overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start + 1]; + st[start + 1] = (cur ? cur + " " : "") + "overlay " + style; + } + } + }, lineClasses); + context.state = state; + context.baseTokens = null; + context.baseTokenPos = 1; + }; + + for (var o = 0; o < cm.state.overlays.length; ++o) { + loop(o); + } + + return { + styles: st, + classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null + }; + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var context = getContextBefore(cm, lineNo(line)); + var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); + var result = highlightLine(cm, line, context); + + if (resetState) { + context.state = resetState; + } + + line.stateAfter = context.save(!resetState); + line.styles = result.styles; + + if (result.classes) { + line.styleClasses = result.classes; + } else if (line.styleClasses) { + line.styleClasses = null; + } + + if (updateFrontier === cm.doc.highlightFrontier) { + cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); + } + } + + return line.styles; + } + + function getContextBefore(cm, n, precise) { + var doc = cm.doc, + display = cm.display; + + if (!doc.mode.startState) { + return new Context(doc, true, n); + } + + var start = findStartLine(cm, n, precise); + var saved = start > doc.first && getLine(doc, start - 1).stateAfter; + var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); + doc.iter(start, n, function (line) { + processLine(cm, line.text, context); + var pos = context.line; + line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; + context.nextLine(); + }); + + if (precise) { + doc.modeFrontier = context.line; + } + + return context; + } // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + + + function processLine(cm, text, context, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize, context); + stream.start = stream.pos = startAt || 0; + + if (text == "") { + callBlankLine(mode, context.state); + } + + while (!stream.eol()) { + readToken(mode, stream, context.state); + stream.start = stream.pos; + } + } + + function callBlankLine(mode, state) { + if (mode.blankLine) { + return mode.blankLine(state); + } + + if (!mode.innerMode) { + return; + } + + var inner = innerMode(mode, state); + + if (inner.mode.blankLine) { + return inner.mode.blankLine(inner.state); + } + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) { + inner[0] = innerMode(mode, state).mode; + } + + var style = mode.token(stream, state); + + if (stream.pos > stream.start) { + return style; + } + } + + throw new Error("Mode " + mode.name + " failed to advance stream."); + } + + var Token = function Token(stream, type, state) { + this.start = stream.start; + this.end = stream.pos; + this.string = stream.current(); + this.type = type || null; + this.state = state; + }; // Utility for getTokenAt and getLineTokens + + + function takeToken(cm, pos, precise, asArray) { + var doc = cm.doc, + mode = doc.mode, + style; + pos = _clipPos(doc, pos); + var line = getLine(doc, pos.line), + context = getContextBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize, context), + tokens; + + if (asArray) { + tokens = []; + } + + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, context.state); + + if (asArray) { + tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); + } + } + + return asArray ? tokens : new Token(stream, style, context.state); + } + + function extractLineClasses(type, output) { + if (type) { + for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + + if (!lineClass) { + break; + } + + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + + if (output[prop] == null) { + output[prop] = lineClass[2]; + } else if (!new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)").test(output[prop])) { + output[prop] += " " + lineClass[2]; + } + } + } + + return type; + } // Run the given mode's parser over a line, calling f for each token. + + + function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + + if (flattenSpans == null) { + flattenSpans = cm.options.flattenSpans; + } + + var curStart = 0, + curStyle = null; + var stream = new StringStream(text, cm.options.tabSize, context), + style; + var inner = cm.options.addModeClass && [null]; + + if (text == "") { + extractLineClasses(callBlankLine(mode, context.state), lineClasses); + } + + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + + if (forceToEnd) { + processLine(cm, text, context, stream.pos); + } + + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); + } + + if (inner) { + var mName = inner[0].name; + + if (mName) { + style = "m-" + (style ? mName + " " + style : mName); + } + } + + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 5000); + f(curStart, curStyle); + } + + curStyle = style; + } + + stream.start = stream.pos; + } + + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 + // characters, and returns inaccurate measurements in nodes + // starting around 5000 chars. + var pos = Math.min(stream.pos, curStart + 5000); + f(pos, curStyle); + curStart = pos; + } + } // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + + + function findStartLine(cm, n, precise) { + var minindent, + minline, + doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + + for (var search = n; search > lim; --search) { + if (search <= doc.first) { + return doc.first; + } + + var line = getLine(doc, search - 1), + after = line.stateAfter; + + if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) { + return search; + } + + var indented = countColumn(line.text, null, cm.options.tabSize); + + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + + return minline; + } + + function retreatFrontier(doc, n) { + doc.modeFrontier = Math.min(doc.modeFrontier, n); + + if (doc.highlightFrontier < n - 10) { + return; + } + + var start = doc.first; + + for (var line = n - 1; line > start; line--) { + var saved = getLine(doc, line).stateAfter; // change is on 3 + // state on line 1 looked ahead 2 -- so saw 3 + // test 1 + 2 < 3 should cover this + + if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { + start = line + 1; + break; + } + } + + doc.highlightFrontier = Math.min(doc.highlightFrontier, start); + } // Optimize some code when these features are not used. + + + var sawReadOnlySpans = false, + sawCollapsedSpans = false; + + function seeReadOnlySpans() { + sawReadOnlySpans = true; + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true; + } // TEXTMARKER SPANS + + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; + this.to = to; + } // Search an array of spans for a span matching the given marker. + + + function getMarkedSpanFor(spans, marker) { + if (spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + + if (span.marker == marker) { + return span; + } + } + } + } // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + + + function removeMarkedSpan(spans, span) { + var r; + + for (var i = 0; i < spans.length; ++i) { + if (spans[i] != span) { + (r || (r = [])).push(spans[i]); + } + } + + return r; + } // Add a span to a line. + + + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + + + function markedSpansBefore(old, startCh, isInsert) { + var nw; + + if (old) { + for (var i = 0; i < old.length; ++i) { + var span = old[i], + marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } + } + + return nw; + } + + function markedSpansAfter(old, endCh, isInsert) { + var nw; + + if (old) { + for (var i = 0; i < old.length; ++i) { + var span = old[i], + marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, span.to == null ? null : span.to - endCh)); + } + } + } + + return nw; + } // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + + + function stretchSpansOverChange(doc, change) { + if (change.full) { + return null; + } + + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + + if (!oldFirst && !oldLast) { + return null; + } + + var startCh = change.from.ch, + endCh = change.to.ch, + isInsert = cmp(change.from, change.to) == 0; // Get the spans that 'stick out' on both sides + + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); // Next, merge those two ends + + var sameLine = change.text.length == 1, + offset = lst(change.text).length + (sameLine ? startCh : 0); + + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + + if (!found) { + span.to = startCh; + } else if (sameLine) { + span.to = found.to == null ? null : found.to + offset; + } + } + } + } + + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1]; + + if (span$1.to != null) { + span$1.to += offset; + } + + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker); + + if (!found$1) { + span$1.from = offset; + + if (sameLine) { + (first || (first = [])).push(span$1); + } + } + } else { + span$1.from += offset; + + if (sameLine) { + (first || (first = [])).push(span$1); + } + } + } + } // Make sure we didn't create any zero-length spans + + + if (first) { + first = clearEmptySpans(first); + } + + if (last && last != first) { + last = clearEmptySpans(last); + } + + var newMarkers = [first]; + + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, + gapMarkers; + + if (gap > 0 && first) { + for (var i$2 = 0; i$2 < first.length; ++i$2) { + if (first[i$2].to == null) { + (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); + } + } + } + + for (var i$3 = 0; i$3 < gap; ++i$3) { + newMarkers.push(gapMarkers); + } + + newMarkers.push(last); + } + + return newMarkers; + } // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + + + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) { + spans.splice(i--, 1); + } + } + + if (!spans.length) { + return null; + } + + return spans; + } // Used to 'clip' out readOnly ranges when making a change. + + + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { + for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) { + (markers || (markers = [])).push(mark); + } + } + } + }); + + if (!markers) { + return null; + } + + var parts = [{ + from: from, + to: to + }]; + + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], + m = mk.find(0); + + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { + continue; + } + + var newParts = [j, 1], + dfrom = cmp(p.from, m.from), + dto = cmp(p.to, m.to); + + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) { + newParts.push({ + from: p.from, + to: m.from + }); + } + + if (dto > 0 || !mk.inclusiveRight && !dto) { + newParts.push({ + from: m.to, + to: p.to + }); + } + + parts.splice.apply(parts, newParts); + j += newParts.length - 3; + } + } + + return parts; + } // Connect or disconnect spans from a line. + + + function detachMarkedSpans(line) { + var spans = line.markedSpans; + + if (!spans) { + return; + } + + for (var i = 0; i < spans.length; ++i) { + spans[i].marker.detachLine(line); + } + + line.markedSpans = null; + } + + function attachMarkedSpans(line, spans) { + if (!spans) { + return; + } + + for (var i = 0; i < spans.length; ++i) { + spans[i].marker.attachLine(line); + } + + line.markedSpans = spans; + } // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + + + function extraLeft(marker) { + return marker.inclusiveLeft ? -1 : 0; + } + + function extraRight(marker) { + return marker.inclusiveRight ? 1 : 0; + } // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + + + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + + if (lenDiff != 0) { + return lenDiff; + } + + var aPos = a.find(), + bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + + if (fromCmp) { + return -fromCmp; + } + + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + + if (toCmp) { + return toCmp; + } + + return b.id - a.id; + } // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + + + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, + found; + + if (sps) { + for (var sp = void 0, i = 0; i < sps.length; ++i) { + sp = sps[i]; + + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { + found = sp.marker; + } + } + } + + return found; + } + + function collapsedSpanAtStart(line) { + return collapsedSpanAtSide(line, true); + } + + function collapsedSpanAtEnd(line) { + return collapsedSpanAtSide(line, false); + } + + function collapsedSpanAround(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, + found; + + if (sps) { + for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + + if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { + found = sp.marker; + } + } + } + + return found; + } // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + + + function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) { + var line = getLine(doc, lineNo$$1); + var sps = sawCollapsedSpans && line.markedSpans; + + if (sps) { + for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + + if (!sp.marker.collapsed) { + continue; + } + + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { + continue; + } + + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) { + return true; + } + } + } + } // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + + + function visualLine(line) { + var merged; + + while (merged = collapsedSpanAtStart(line)) { + line = merged.find(-1, true).line; + } + + return line; + } + + function visualLineEnd(line) { + var merged; + + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + } + + return line; + } // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + + + function visualLineContinued(line) { + var merged, lines; + + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + (lines || (lines = [])).push(line); + } + + return lines; + } // Get the line number of the start of the visual line that the + // given line number is part of. + + + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), + vis = visualLine(line); + + if (line == vis) { + return lineN; + } + + return lineNo(vis); + } // Get the line number of the start of the next visual line after + // the given line. + + + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { + return lineN; + } + + var line = getLine(doc, lineN), + merged; + + if (!lineIsHidden(doc, line)) { + return lineN; + } + + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + } + + return lineNo(line) + 1; + } // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + + + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + + if (sps) { + for (var sp = void 0, i = 0; i < sps.length; ++i) { + sp = sps[i]; + + if (!sp.marker.collapsed) { + continue; + } + + if (sp.from == null) { + return true; + } + + if (sp.marker.widgetNode) { + continue; + } + + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) { + return true; + } + } + } + } + + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); + } + + if (span.marker.inclusiveRight && span.to == line.text.length) { + return true; + } + + for (var sp = void 0, i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && (sp.to == null || sp.to != span.from) && (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && lineIsHiddenInner(doc, line, sp)) { + return true; + } + } + } // Find the height above the given line. + + + function _heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + var h = 0, + chunk = lineObj.parent; + + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + + if (line == lineObj) { + break; + } else { + h += line.height; + } + } + + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1]; + + if (cur == chunk) { + break; + } else { + h += cur.height; + } + } + } + + return h; + } // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + + + function lineLength(line) { + if (line.height == 0) { + return 0; + } + + var len = line.text.length, + merged, + cur = line; + + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + + cur = line; + + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true); + len -= cur.text.length - found$1.from.ch; + cur = found$1.to.line; + len += cur.text.length - found$1.to.ch; + } + + return len; + } // Find the longest line in the document. + + + function findMaxLine(cm) { + var d = cm.display, + doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function (line) { + var len = lineLength(line); + + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } // LINE DATA STRUCTURE + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + + + var Line = function Line(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + + Line.prototype.lineNo = function () { + return lineNo(this); + }; + + eventMixin(Line); // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + + if (line.stateAfter) { + line.stateAfter = null; + } + + if (line.styles) { + line.styles = null; + } + + if (line.order != null) { + line.order = null; + } + + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + + if (estHeight != line.height) { + updateLineHeight(line, estHeight); + } + } // Detach a line from the document tree and its markers. + + + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + + + var styleToClassCache = {}, + styleToClassCacheWithMode = {}; + + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) { + return null; + } + + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || (cache[style] = style.replace(/\S+/g, "cm-$&")); + } // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + + + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = { + pre: eltP("pre", [content], "CodeMirror-line"), + content: content, + col: 0, + pos: 0, + cm: cm, + trailingSpace: false, + splitSpaces: cm.getOption("lineWrapping") + }; + lineView.measure = {}; // Iterate over the logical lines that make up this visual line. + + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, + order = void 0; + builder.pos = 0; + builder.addToken = buildToken; // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) { + builder.addToken = buildTokenBadBidi(builder.addToken, order); + } + + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + + if (line.styleClasses) { + if (line.styleClasses.bgClass) { + builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); + } + + if (line.styleClasses.textClass) { + builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); + } + } // Ensure at least a single node is present, for measuring. + + + if (builder.map.length == 0) { + builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); + } // Store the map and a cache object for the current logical line + + + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); + (lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } // See issue #2901 + + + if (webkit) { + var last = builder.content.lastChild; + + if (/\bcm-tab\b/.test(last.className) || last.querySelector && last.querySelector(".cm-tab")) { + builder.content.className = "cm-tab-wrap-hack"; + } + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + + if (builder.pre.className) { + builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); + } + + return builder; + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token; + } // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + + + function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { + if (!text) { + return; + } + + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; + var special = builder.cm.state.specialChars, + mustWrap = false; + var content; + + if (!special.test(text)) { + builder.col += text.length; + content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + + if (ie && ie_version < 9) { + mustWrap = true; + } + + builder.pos += text.length; + } else { + content = document.createDocumentFragment(); + var pos = 0; + + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + + if (ie && ie_version < 9) { + content.appendChild(elt("span", [txt])); + } else { + content.appendChild(txt); + } + + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + + if (!m) { + break; + } + + pos += skipped + 1; + var txt$1 = void 0; + + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, + tabWidth = tabSize - builder.col % tabSize; + txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt$1.setAttribute("role", "presentation"); + txt$1.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240D" : "\u2424", "cm-invalidchar")); + txt$1.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); + txt$1.setAttribute("cm-text", m[0]); + + if (ie && ie_version < 9) { + content.appendChild(elt("span", [txt$1])); + } else { + content.appendChild(txt$1); + } + + builder.col += 1; + } + + builder.map.push(builder.pos, builder.pos + 1, txt$1); + builder.pos++; + } + } + + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; + + if (style || startStyle || endStyle || mustWrap || css) { + var fullStyle = style || ""; + + if (startStyle) { + fullStyle += startStyle; + } + + if (endStyle) { + fullStyle += endStyle; + } + + var token = elt("span", [content], fullStyle, css); + + if (attributes) { + for (var attr in attributes) { + if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") { + token.setAttribute(attr, attributes[attr]); + } + } + } + + return builder.content.appendChild(token); + } + + builder.content.appendChild(content); + } // Change some spaces to NBSP to prevent the browser from collapsing + // trailing spaces at the end of a line when rendering text (issue #1362). + + + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) { + return text; + } + + var spaceBefore = trailingBefore, + result = ""; + + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) { + ch = "\xA0"; + } + + result += ch; + spaceBefore = ch == " "; + } + + return result; + } // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + + + function buildTokenBadBidi(inner, order) { + return function (builder, text, style, startStyle, endStyle, css, attributes) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, + end = start + text.length; + + for (;;) { + // Find the part that overlaps with the start of this text + var part = void 0; + + for (var i = 0; i < order.length; i++) { + part = order[i]; + + if (part.to > start && part.from <= start) { + break; + } + } + + if (part.to >= end) { + return inner(builder, text, style, startStyle, endStyle, css, attributes); + } + + inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + }; + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + + if (widget) { + builder.map.push(builder.pos, builder.pos + size, widget); + } + + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) { + widget = builder.content.appendChild(document.createElement("span")); + } + + widget.setAttribute("cm-marker", marker.id); + } + + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + + builder.pos += size; + builder.trailingSpace = false; + } // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + + + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, + allText = line.text, + at = 0; + + if (!spans) { + for (var i$1 = 1; i$1 < styles.length; i$1 += 2) { + builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1 + 1], builder.cm.options)); + } + + return; + } + + var len = allText.length, + pos = 0, + i = 1, + text = "", + style, + css; + var nextChange = 0, + spanStyle, + spanEndStyle, + spanStartStyle, + collapsed, + attributes; + + for (;;) { + if (nextChange == pos) { + // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = css = ""; + attributes = null; + collapsed = null; + nextChange = Infinity; + var foundBookmarks = [], + endStyles = void 0; + + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], + m = sp.marker; + + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + + if (m.className) { + spanStyle += " " + m.className; + } + + if (m.css) { + css = (css ? css + ";" : "") + m.css; + } + + if (m.startStyle && sp.from == pos) { + spanStartStyle += " " + m.startStyle; + } + + if (m.endStyle && sp.to == nextChange) { + (endStyles || (endStyles = [])).push(m.endStyle, sp.to); + } // support for the old title property + // https://github.com/codemirror/CodeMirror/pull/5673 + + + if (m.title) { + (attributes || (attributes = {})).title = m.title; + } + + if (m.attributes) { + for (var attr in m.attributes) { + (attributes || (attributes = {}))[attr] = m.attributes[attr]; + } + } + + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) { + collapsed = sp; + } + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + + if (endStyles) { + for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) { + if (endStyles[j$1 + 1] == nextChange) { + spanEndStyle += " " + endStyles[j$1]; + } + } + } + + if (!collapsed || collapsed.from == pos) { + for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) { + buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); + } + } + + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, collapsed.marker, collapsed.from == null); + + if (collapsed.to == null) { + return; + } + + if (collapsed.to == pos) { + collapsed = false; + } + } + } + + if (pos >= len) { + break; + } + + var upto = Math.min(len, nextChange); + + while (true) { + if (text) { + var end = pos + text.length; + + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); + } + + if (end >= upto) { + text = text.slice(upto - pos); + pos = upto; + break; + } + + pos = end; + spanStartStyle = ""; + } + + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + + + function LineView(doc, line, lineN) { + // The starting line + this.line = line; // Continuing lines, if any + + this.rest = visualLineContinued(line); // Number of logical lines in this visual line + + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } // Create a range of LineView objects for the given lines. + + + function buildViewArray(cm, from, to) { + var array = [], + nextPos; + + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + + return array; + } + + var operationGroup = null; + + function pushOperation(op) { + if (operationGroup) { + operationGroup.ops.push(op); + } else { + op.ownsGroup = operationGroup = { + ops: [op], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, + i = 0; + + do { + for (; i < callbacks.length; i++) { + callbacks[i].call(null); + } + + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + + if (op.cursorActivityHandlers) { + while (op.cursorActivityCalled < op.cursorActivityHandlers.length) { + op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); + } + } + } + } while (i < callbacks.length); + } + + function finishOperation(op, endCb) { + var group = op.ownsGroup; + + if (!group) { + return; + } + + try { + fireCallbacksForOps(group); + } finally { + operationGroup = null; + endCb(group); + } + } + + var orphanDelayedCallbacks = null; // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + + function signalLater(emitter, type + /*, values...*/ + ) { + var arr = getHandlers(emitter, type); + + if (!arr.length) { + return; + } + + var args = Array.prototype.slice.call(arguments, 2), + list; + + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + + var loop = function loop(i) { + list.push(function () { + return arr[i].apply(null, args); + }); + }; + + for (var i = 0; i < arr.length; ++i) { + loop(i); + } + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + + for (var i = 0; i < delayed.length; ++i) { + delayed[i](); + } + } // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + + + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + + if (type == "text") { + updateLineText(cm, lineView); + } else if (type == "gutter") { + updateLineGutter(cm, lineView, lineN, dims); + } else if (type == "class") { + updateLineClasses(cm, lineView); + } else if (type == "widget") { + updateLineWidgets(cm, lineView, dims); + } + } + + lineView.changes = null; + } // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + + + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + + if (lineView.text.parentNode) { + lineView.text.parentNode.replaceChild(lineView.node, lineView.text); + } + + lineView.node.appendChild(lineView.text); + + if (ie && ie_version < 8) { + lineView.node.style.zIndex = 2; + } + } + + return lineView.node; + } + + function updateLineBackground(cm, lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + + if (cls) { + cls += " CodeMirror-linebackground"; + } + + if (lineView.background) { + if (cls) { + lineView.background.className = cls; + } else { + lineView.background.parentNode.removeChild(lineView.background); + lineView.background = null; + } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + cm.display.input.setUneditable(lineView.background); + } + } // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + + + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built; + } + + return buildLineContent(cm, lineView); + } // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + + + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + + if (lineView.text == lineView.node) { + lineView.node = built.pre; + } + + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(cm, lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(cm, lineView) { + updateLineBackground(cm, lineView); + + if (lineView.line.wrapClass) { + ensureLineWrapped(lineView).className = lineView.line.wrapClass; + } else if (lineView.node != lineView.text) { + lineView.node.className = ""; + } + + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + dims.gutterTotalWidth + "px"); + cm.display.input.setUneditable(lineView.gutterBackground); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + + var markers = lineView.line.gutterMarkers; + + if (cm.options.lineNumbers || markers) { + var wrap$1 = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"); + cm.display.input.setUneditable(gutterWrap); + wrap$1.insertBefore(gutterWrap, lineView.text); + + if (lineView.line.gutterClass) { + gutterWrap.className += " " + lineView.line.gutterClass; + } + + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) { + lineView.lineNumber = gutterWrap.appendChild(elt("div", lineNumberFor(cm.options, lineN), "CodeMirror-linenumber CodeMirror-gutter-elt", "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " + cm.display.lineNumInnerWidth + "px")); + } + + if (markers) { + for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { + var id = cm.display.gutterSpecs[k].className, + found = markers.hasOwnProperty(id) && markers[id]; + + if (found) { + gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); + } + } + } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) { + lineView.alignable = null; + } + + for (var node = lineView.node.firstChild, next = void 0; node; node = next) { + next = node.nextSibling; + + if (node.className == "CodeMirror-linewidget") { + lineView.node.removeChild(node); + } + } + + insertLineWidgets(cm, lineView, dims); + } // Build a line's DOM representation from scratch + + + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + + if (built.bgClass) { + lineView.bgClass = built.bgClass; + } + + if (built.textClass) { + lineView.textClass = built.textClass; + } + + updateLineClasses(cm, lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node; + } // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + + + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + + if (lineView.rest) { + for (var i = 0; i < lineView.rest.length; i++) { + insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); + } + } + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) { + return; + } + + var wrap = ensureLineWrapped(lineView); + + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], + node = elt("div", [widget.node], "CodeMirror-linewidget"); + + if (!widget.handleMouseEvents) { + node.setAttribute("cm-ignore-events", "true"); + } + + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + + if (allowAbove && widget.above) { + wrap.insertBefore(node, lineView.gutter || lineView.text); + } else { + wrap.appendChild(node); + } + + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + + node.style.width = width + "px"; + } + + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + + if (!widget.noHScroll) { + node.style.marginLeft = -dims.gutterTotalWidth + "px"; + } + } + } + + function widgetHeight(widget) { + if (widget.height != null) { + return widget.height; + } + + var cm = widget.doc.cm; + + if (!cm) { + return 0; + } + + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + + if (widget.coverGutter) { + parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; + } + + if (widget.noHScroll) { + parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; + } + + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + + return widget.height = widget.node.parentNode.offsetHeight; + } // Return true when the given mouse event happened in a widget + + + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true" || n.parentNode == display.sizer && n != display.mover) { + return true; + } + } + } // POSITION MEASUREMENT + + + function paddingTop(display) { + return display.lineSpace.offsetTop; + } + + function paddingVert(display) { + return display.mover.offsetHeight - display.lineSpace.offsetHeight; + } + + function paddingH(display) { + if (display.cachedPaddingH) { + return display.cachedPaddingH; + } + + var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = { + left: parseInt(style.paddingLeft), + right: parseInt(style.paddingRight) + }; + + if (!isNaN(data.left) && !isNaN(data.right)) { + display.cachedPaddingH = data; + } + + return data; + } + + function scrollGap(cm) { + return scrollerGap - cm.display.nativeBarWidth; + } + + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; + } + + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; + } // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + + + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], + next = rects[i + 1]; + + if (Math.abs(cur.bottom - next.bottom) > 2) { + heights.push((cur.bottom + next.top) / 2 - rect.top); + } + } + } + + heights.push(rect.bottom - rect.top); + } + } // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + + + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) { + return { + map: lineView.measure.map, + cache: lineView.measure.cache + }; + } + + for (var i = 0; i < lineView.rest.length; i++) { + if (lineView.rest[i] == line) { + return { + map: lineView.measure.maps[i], + cache: lineView.measure.caches[i] + }; + } + } + + for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) { + if (lineNo(lineView.rest[i$1]) > lineN) { + return { + map: lineView.measure.maps[i$1], + cache: lineView.measure.caches[i$1], + before: true + }; + } + } + } // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + + + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view; + } // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + + + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); + } // Find a line view that corresponds to the given line number. + + + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) { + return cm.display.view[findViewIndex(cm, lineN)]; + } + + var ext = cm.display.externalMeasured; + + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) { + return ext; + } + } // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + + + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + + if (!view) { + view = updateExternalMeasurement(cm, line); + } + + var info = mapFromLineView(view, line, lineN); + return { + line: line, + view: view, + rect: null, + map: info.map, + cache: info.cache, + before: info.before, + hasHeights: false + }; + } // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + + + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) { + ch = -1; + } + + var key = ch + (bias || ""), + found; + + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) { + prepared.rect = prepared.view.text.getBoundingClientRect(); + } + + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + + found = measureCharInner(cm, prepared, ch, bias); + + if (!found.bogus) { + prepared.cache[key] = found; + } + } + + return { + left: found.left, + right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom + }; + } + + var nullRect = { + left: 0, + right: 0, + top: 0, + bottom: 0 + }; + + function nodeAndOffsetInLineMap(map$$1, ch, bias) { + var node, start, end, collapse, mStart, mEnd; // First, search the line map for the text node corresponding to, + // or closest to, the target character. + + for (var i = 0; i < map$$1.length; i += 3) { + mStart = map$$1[i]; + mEnd = map$$1[i + 1]; + + if (ch < mStart) { + start = 0; + end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + + if (ch >= mEnd) { + collapse = "right"; + } + } + + if (start != null) { + node = map$$1[i + 2]; + + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) { + collapse = bias; + } + + if (bias == "left" && start == 0) { + while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) { + node = map$$1[(i -= 3) + 2]; + collapse = "left"; + } + } + + if (bias == "right" && start == mEnd - mStart) { + while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) { + node = map$$1[(i += 3) + 2]; + collapse = "right"; + } + } + + break; + } + } + + return { + node: node, + start: start, + end: end, + collapse: collapse, + coverStart: mStart, + coverEnd: mEnd + }; + } + + function getUsefulRect(rects, bias) { + var rect = nullRect; + + if (bias == "left") { + for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) { + break; + } + } + } else { + for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { + if ((rect = rects[i$1]).left != rect.right) { + break; + } + } + } + + return rect; + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, + start = place.start, + end = place.end, + collapse = place.collapse; + var rect; + + if (node.nodeType == 3) { + // If it is a text node, use a range to retrieve the coordinates. + for (var i$1 = 0; i$1 < 4; i$1++) { + // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { + --start; + } + + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { + ++end; + } + + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { + rect = node.parentNode.getBoundingClientRect(); + } else { + rect = getUsefulRect(range(node, start, end).getClientRects(), bias); + } + + if (rect.left || rect.right || start == 0) { + break; + } + + end = start; + start = start - 1; + collapse = "right"; + } + + if (ie && ie_version < 11) { + rect = maybeUpdateRectForZooming(cm.display.measure, rect); + } + } else { + // If it is a widget, simply get the box for the whole widget. + if (start > 0) { + collapse = bias = "right"; + } + + var rects; + + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) { + rect = rects[bias == "right" ? rects.length - 1 : 0]; + } else { + rect = node.getBoundingClientRect(); + } + } + + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + + if (rSpan) { + rect = { + left: rSpan.left, + right: rSpan.left + charWidth(cm.display), + top: rSpan.top, + bottom: rSpan.bottom + }; + } else { + rect = nullRect; + } + } + + var rtop = rect.top - prepared.rect.top, + rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + var i = 0; + + for (; i < heights.length - 1; i++) { + if (mid < heights[i]) { + break; + } + } + + var top = i ? heights[i - 1] : 0, + bot = heights[i]; + var result = { + left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, + bottom: bot + }; + + if (!rect.left && !rect.right) { + result.bogus = true; + } + + if (!cm.options.singleCursorHeightPerLine) { + result.rtop = rtop; + result.rbottom = rbot; + } + + return result; + } // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + + + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) { + return rect; + } + + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return { + left: rect.left * scaleX, + right: rect.right * scaleX, + top: rect.top * scaleY, + bottom: rect.bottom * scaleY + }; + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + + if (lineView.rest) { + for (var i = 0; i < lineView.rest.length; i++) { + lineView.measure.caches[i] = {}; + } + } + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + + for (var i = 0; i < cm.display.view.length; i++) { + clearLineMeasurementCacheFor(cm.display.view[i]); + } + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + + if (!cm.options.lineWrapping) { + cm.display.maxLineChanged = true; + } + + cm.display.lineNumChars = null; + } + + function pageScrollX() { + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + // which causes page_Offset and bounding client rects to use + // different reference viewports and invalidate our calculations. + if (chrome && android) { + return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)); + } + + return window.pageXOffset || (document.documentElement || document.body).scrollLeft; + } + + function pageScrollY() { + if (chrome && android) { + return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)); + } + + return window.pageYOffset || (document.documentElement || document.body).scrollTop; + } + + function widgetTopHeight(lineObj) { + var height = 0; + + if (lineObj.widgets) { + for (var i = 0; i < lineObj.widgets.length; ++i) { + if (lineObj.widgets[i].above) { + height += widgetHeight(lineObj.widgets[i]); + } + } + } + + return height; + } // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"./null (editor), "window", + // or "page". + + + function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { + if (!includeWidgets) { + var height = widgetTopHeight(lineObj); + rect.top += height; + rect.bottom += height; + } + + if (context == "line") { + return rect; + } + + if (!context) { + context = "local"; + } + + var yOff = _heightAtLine(lineObj); + + if (context == "local") { + yOff += paddingTop(cm.display); + } else { + yOff -= cm.display.viewOffset; + } + + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); + rect.left += xOff; + rect.right += xOff; + } + + rect.top += yOff; + rect.bottom += yOff; + return rect; + } // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"./null. + + + function fromCoordSystem(cm, coords, context) { + if (context == "div") { + return coords; + } + + var left = coords.left, + top = coords.top; // First move into "page" coordinate system + + if (context == "page") { + left -= pageScrollX(); + top -= pageScrollY(); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return { + left: left - lineSpaceBox.left, + top: top - lineSpaceBox.top + }; + } + + function _charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) { + lineObj = getLine(cm.doc, pos.line); + } + + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); + } // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` + // and after `char - 1` in writing order of `char - 1` + // A cursor Pos(line, char, "after") is on the same visual line as `char` + // and before `char` in writing order of `char` + // Examples (upper-case letters are RTL, lower-case are LTR): + // Pos(0, 1, ...) + // before after + // ab a|b a|b + // aB a|B aB| + // Ab |Ab A|b + // AB B|A B|A + // Every position after the last character on a line is considered to stick + // to the last character on the line. + + + function _cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + + if (!preparedMeasure) { + preparedMeasure = prepareMeasureForLine(cm, lineObj); + } + + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + + if (right) { + m.left = m.right; + } else { + m.right = m.left; + } + + return intoCoordSystem(cm, lineObj, m, context); + } + + var order = getOrder(lineObj, cm.doc.direction), + ch = pos.ch, + sticky = pos.sticky; + + if (ch >= lineObj.text.length) { + ch = lineObj.text.length; + sticky = "before"; + } else if (ch <= 0) { + ch = 0; + sticky = "after"; + } + + if (!order) { + return get(sticky == "before" ? ch - 1 : ch, sticky == "before"); + } + + function getBidi(ch, partPos, invert) { + var part = order[partPos], + right = part.level == 1; + return get(invert ? ch - 1 : ch, right != invert); + } + + var partPos = getBidiPartAt(order, ch, sticky); + var other = bidiOther; + var val = getBidi(ch, partPos, sticky == "before"); + + if (other != null) { + val.other = getBidi(ch, other, sticky != "before"); + } + + return val; + } // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + + + function estimateCoords(cm, pos) { + var left = 0; + pos = _clipPos(cm.doc, pos); + + if (!cm.options.lineWrapping) { + left = charWidth(cm.display) * pos.ch; + } + + var lineObj = getLine(cm.doc, pos.line); + var top = _heightAtLine(lineObj) + paddingTop(cm.display); + return { + left: left, + right: left, + top: top, + bottom: top + lineObj.height + }; + } // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + + + function PosWithInfo(line, ch, sticky, outside, xRel) { + var pos = Pos(line, ch, sticky); + pos.xRel = xRel; + + if (outside) { + pos.outside = outside; + } + + return pos; + } // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + + + function _coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + + if (y < 0) { + return PosWithInfo(doc.first, 0, null, -1, -1); + } + + var lineN = _lineAtHeight(doc, y), + last = doc.first + doc.size - 1; + + if (lineN > last) { + return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1); + } + + if (x < 0) { + x = 0; + } + + var lineObj = getLine(doc, lineN); + + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); + + if (!collapsed) { + return found; + } + + var rangeEnd = collapsed.find(1); + + if (rangeEnd.line == lineN) { + return rangeEnd; + } + + lineObj = getLine(doc, lineN = rangeEnd.line); + } + } + + function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { + y -= widgetTopHeight(lineObj); + var end = lineObj.text.length; + var begin = findFirst(function (ch) { + return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; + }, end, 0); + end = findFirst(function (ch) { + return measureCharPrepared(cm, preparedMeasure, ch).top > y; + }, begin, end); + return { + begin: begin, + end: end + }; + } + + function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { + preparedMeasure = prepareMeasureForLine(cm, lineObj); + } + + var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; + return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop); + } // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + + + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x; + } + + function coordsCharInner(cm, lineObj, lineNo$$1, x, y) { + // Move y into line-local coordinate space + y -= _heightAtLine(lineObj); + var preparedMeasure = prepareMeasureForLine(cm, lineObj); // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + + var widgetHeight$$1 = widgetTopHeight(lineObj); + var begin = 0, + end = lineObj.text.length, + ltr = true; + var order = getOrder(lineObj, cm.doc.direction); // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. + + if (order) { + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y); + ltr = part.level != 1; // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + + begin = ltr ? part.from : part.to - 1; + end = ltr ? part.to : part.from - 1; + } // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + + + var chAround = null, + boxAround = null; + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch); + box.top += widgetHeight$$1; + box.bottom += widgetHeight$$1; + + if (!boxIsAfter(box, x, y, false)) { + return false; + } + + if (box.top <= y && box.left <= x) { + chAround = ch; + boxAround = box; + } + + return true; + }, begin, end); + var baseX, + sticky, + outside = false; // If a box around the coordinates was found, use that + + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, + atStart = atLeft == ltr; + ch = chAround + (atStart ? 0 : 1); + sticky = atStart ? "after" : "before"; + baseX = atLeft ? boxAround.left : boxAround.right; + } else { + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { + ch++; + } // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + + + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y == ltr ? "after" : "before"; // Now get accurate coordinates for this place, in order to get a + // base X position + + var coords = _cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure); + + baseX = coords.left; + outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; + } + + ch = skipExtendingChars(lineObj.text, ch, 1); + return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX); + } + + function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], + ltr = part.level != 1; + return boxIsAfter(_cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"), "line", lineObj, preparedMeasure), x, y, true); + }, 0, order.length - 1); + var part = order[index]; // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + + if (index > 0) { + var ltr = part.level != 1; + + var start = _cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"), "line", lineObj, preparedMeasure); + + if (boxIsAfter(start, x, y, true) && start.top > y) { + part = order[index - 1]; + } + } + + return part; + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + + if (/\s/.test(lineObj.text.charAt(end - 1))) { + end--; + } + + var part = null, + closestDist = null; + + for (var i = 0; i < order.length; i++) { + var p = order[i]; + + if (p.from >= end || p.to <= begin) { + continue; + } + + var ltr = p.level != 1; + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + + var dist = endX < x ? x - endX + 1e9 : endX - x; + + if (!part || closestDist > dist) { + part = p; + closestDist = dist; + } + } + + if (!part) { + part = order[order.length - 1]; + } // Clip the part to the wrapped line. + + + if (part.from < begin) { + part = { + from: begin, + to: part.to, + level: part.level + }; + } + + if (part.to > end) { + part = { + from: part.from, + to: end, + level: part.level + }; + } + + return part; + } + + var measureText; // Compute the default text height. + + function textHeight(display) { + if (display.cachedTextHeight != null) { + return display.cachedTextHeight; + } + + if (measureText == null) { + measureText = elt("pre", null, "CodeMirror-line-like"); // Measure a bunch of lines, for browsers that compute + // fractional heights. + + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + + measureText.appendChild(document.createTextNode("x")); + } + + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + + if (height > 3) { + display.cachedTextHeight = height; + } + + removeChildren(display.measure); + return height || 1; + } // Compute the default character width. + + + function charWidth(display) { + if (display.cachedCharWidth != null) { + return display.cachedCharWidth; + } + + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor], "CodeMirror-line-like"); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), + width = (rect.right - rect.left) / 10; + + if (width > 2) { + display.cachedCharWidth = width; + } + + return width || 10; + } // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + + + function getDimensions(cm) { + var d = cm.display, + left = {}, + width = {}; + var gutterLeft = d.gutters.clientLeft; + + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + var id = cm.display.gutterSpecs[i].className; + left[id] = n.offsetLeft + n.clientLeft + gutterLeft; + width[id] = n.clientWidth; + } + + return { + fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth + }; + } // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + + + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; + } // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + + + function estimateHeight(cm) { + var th = textHeight(cm.display), + wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function (line) { + if (lineIsHidden(cm.doc, line)) { + return 0; + } + + var widgetsHeight = 0; + + if (line.widgets) { + for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) { + widgetsHeight += line.widgets[i].height; + } + } + } + + if (wrapping) { + return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; + } else { + return widgetsHeight + th; + } + }; + } + + function estimateLineHeights(cm) { + var doc = cm.doc, + est = estimateHeight(cm); + doc.iter(function (line) { + var estHeight = est(line); + + if (estHeight != line.height) { + updateLineHeight(line, estHeight); + } + }); + } // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + + + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { + return null; + } + + var x, + y, + space = display.lineSpace.getBoundingClientRect(); // Fails unpredictably on IE[67] when mouse is dragged around quickly. + + try { + x = e.clientX - space.left; + y = e.clientY - space.top; + } catch (e) { + return null; + } + + var coords = _coordsChar(cm, x, y), + line; + + if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + + return coords; + } // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + + + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) { + return null; + } + + n -= cm.display.viewFrom; + + if (n < 0) { + return null; + } + + var view = cm.display.view; + + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + + if (n < 0) { + return i; + } + } + } // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + + + function regChange(cm, from, to, lendiff) { + if (from == null) { + from = cm.doc.first; + } + + if (to == null) { + to = cm.doc.first + cm.doc.size; + } + + if (!lendiff) { + lendiff = 0; + } + + var display = cm.display; + + if (lendiff && to < display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers > from)) { + display.updateLineNumbers = from; + } + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { + // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) { + resetView(cm); + } + } else if (to <= display.viewFrom) { + // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { + // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { + // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { + // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1); + + if (cut$1) { + display.view = display.view.slice(0, cut$1.index); + display.viewTo = cut$1.lineN; + } else { + resetView(cm); + } + } else { + // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index).concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)).concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + + if (ext) { + if (to < ext.lineN) { + ext.lineN += lendiff; + } else if (from < ext.lineN + ext.size) { + display.externalMeasured = null; + } + } + } // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + + + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, + ext = cm.display.externalMeasured; + + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) { + display.externalMeasured = null; + } + + if (line < display.viewFrom || line >= display.viewTo) { + return; + } + + var lineView = display.view[findViewIndex(cm, line)]; + + if (lineView.node == null) { + return; + } + + var arr = lineView.changes || (lineView.changes = []); + + if (indexOf(arr, type) == -1) { + arr.push(type); + } + } // Clear the view. + + + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), + diff, + view = cm.display.view; + + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) { + return { + index: index, + lineN: newN + }; + } + + var n = cm.display.viewFrom; + + for (var i = 0; i < index; i++) { + n += view[i].size; + } + + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { + return null; + } + + diff = n + view[index].size - oldN; + index++; + } else { + diff = n - oldN; + } + + oldN += diff; + newN += diff; + } + + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { + return null; + } + + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + + return { + index: index, + lineN: newN + }; + } // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + + + function adjustView(cm, from, to) { + var display = cm.display, + view = display.view; + + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) { + display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); + } else if (display.viewFrom < from) { + display.view = display.view.slice(findViewIndex(cm, from)); + } + + display.viewFrom = from; + + if (display.viewTo < to) { + display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); + } else if (display.viewTo > to) { + display.view = display.view.slice(0, findViewIndex(cm, to)); + } + } + + display.viewTo = to; + } // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + + + function countDirtyView(cm) { + var view = cm.display.view, + dirty = 0; + + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + + if (!lineView.hidden && (!lineView.node || lineView.changes)) { + ++dirty; + } + } + + return dirty; + } + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + if (primary === void 0) primary = true; + var doc = cm.doc, + result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (!primary && i == doc.sel.primIndex) { + continue; + } + + var range$$1 = doc.sel.ranges[i]; + + if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { + continue; + } + + var collapsed = range$$1.empty(); + + if (collapsed || cm.options.showCursorWhenSelecting) { + drawSelectionCursor(cm, range$$1.head, curFragment); + } + + if (!collapsed) { + drawSelectionRange(cm, range$$1, selFragment); + } + } + + return result; + } // Draws a cursor for the given range + + + function drawSelectionCursor(cm, head, output) { + var pos = _cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\xA0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\xA0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + function cmpCoords(a, b) { + return a.top - b.top || a.left - b.left; + } // Draws the given range as a highlighted selection + + + function drawSelectionRange(cm, range$$1, output) { + var display = cm.display, + doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), + leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + var docLTR = doc.direction == "ltr"; + + function add(left, top, width, bottom) { + if (top < 0) { + top = 0; + } + + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px")); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + + function coords(ch, bias) { + return _charCoords(cm, Pos(line, ch), "div", lineObj, bias); + } + + function wrapX(pos, dir, side) { + var extent = wrappedLineExtentChar(cm, lineObj, null, pos); + var prop = dir == "ltr" == (side == "after") ? "left" : "right"; + var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); + return coords(ch, prop)[prop]; + } + + var order = getOrder(lineObj, doc.direction); + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var ltr = dir == "ltr"; + var fromPos = coords(from, ltr ? "left" : "right"); + var toPos = coords(to - 1, ltr ? "right" : "left"); + var openStart = fromArg == null && from == 0, + openEnd = toArg == null && to == lineLen; + var first = i == 0, + last = !order || i == order.length - 1; + + if (toPos.top - fromPos.top <= 3) { + // Single line + var openLeft = (docLTR ? openStart : openEnd) && first; + var openRight = (docLTR ? openEnd : openStart) && last; + var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; + var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; + add(left, fromPos.top, right - left, fromPos.bottom); + } else { + // Multiple lines + var topLeft, topRight, botLeft, botRight; + + if (ltr) { + topLeft = docLTR && openStart && first ? leftSide : fromPos.left; + topRight = docLTR ? rightSide : wrapX(from, dir, "before"); + botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); + botRight = docLTR && openEnd && last ? rightSide : toPos.right; + } else { + topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); + topRight = !docLTR && openStart && first ? rightSide : fromPos.right; + botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; + botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); + } + + add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); + + if (fromPos.bottom < toPos.top) { + add(leftSide, fromPos.bottom, null, toPos.top); + } + + add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); + } + + if (!start || cmpCoords(fromPos, start) < 0) { + start = fromPos; + } + + if (cmpCoords(toPos, start) < 0) { + start = toPos; + } + + if (!end || cmpCoords(fromPos, end) < 0) { + end = fromPos; + } + + if (cmpCoords(toPos, end) < 0) { + end = toPos; + } + }); + return { + start: start, + end: end + }; + } + + var sFrom = range$$1.from(), + sTo = range$$1.to(); + + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), + toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + + if (leftEnd.bottom < rightStart.top) { + add(leftSide, leftEnd.bottom, null, rightStart.top); + } + } + + output.appendChild(fragment); + } // Cursor-blinking + + + function restartBlink(cm) { + if (!cm.state.focused) { + return; + } + + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + + if (cm.options.cursorBlinkRate > 0) { + display.blinker = setInterval(function () { + return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); + } else if (cm.options.cursorBlinkRate < 0) { + display.cursorDiv.style.visibility = "hidden"; + } + } + + function ensureFocus(cm) { + if (!cm.state.focused) { + cm.display.input.focus(); + onFocus(cm); + } + } + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function () { + if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + onBlur(cm); + } + }, 100); + } + + function onFocus(cm, e) { + if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + } + + if (cm.options.readOnly == "nocursor") { + return; + } + + if (!cm.state.focused) { + signal(cm, "focus", cm, e); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + + if (webkit) { + setTimeout(function () { + return cm.display.input.reset(true); + }, 20); + } // Issue #1730 + + } + + cm.display.input.receivedFocus(); + } + + restartBlink(cm); + } + + function onBlur(cm, e) { + if (cm.state.delayingBlurEvent) { + return; + } + + if (cm.state.focused) { + signal(cm, "blur", cm, e); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + + clearInterval(cm.display.blinker); + setTimeout(function () { + if (!cm.state.focused) { + cm.display.shift = false; + } + }, 150); + } // Read the actual heights of the rendered lines, and update their + // stored heights to match. + + + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], + wrapping = cm.options.lineWrapping; + var height = void 0, + width = 0; + + if (cur.hidden) { + continue; + } + + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; // Check that lines don't extend past the right of the current + // editor width + + if (!wrapping && cur.text.firstChild) { + width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; + } + } + + var diff = cur.line.height - height; + + if (diff > .005 || diff < -.005) { + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + + if (cur.rest) { + for (var j = 0; j < cur.rest.length; j++) { + updateWidgetHeight(cur.rest[j]); + } + } + } + + if (width > cm.display.sizerWidth) { + var chWidth = Math.ceil(width / charWidth(cm.display)); + + if (chWidth > cm.display.maxLineLength) { + cm.display.maxLineLength = chWidth; + cm.display.maxLine = cur.line; + cm.display.maxLineChanged = true; + } + } + } + } // Read and store the height of line widgets associated with the + // given line. + + + function updateWidgetHeight(line) { + if (line.widgets) { + for (var i = 0; i < line.widgets.length; ++i) { + var w = line.widgets[i], + parent = w.node.parentNode; + + if (parent) { + w.height = parent.offsetHeight; + } + } + } + } // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + + + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = _lineAtHeight(doc, top), + to = _lineAtHeight(doc, bottom); // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + + + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, + ensureTo = viewport.ensure.to.line; + + if (ensureFrom < from) { + from = ensureFrom; + to = _lineAtHeight(doc, _heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = _lineAtHeight(doc, _heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + + return { + from: from, + to: Math.max(to, from + 1) + }; + } // SCROLLING THINGS INTO VIEW + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + + + function maybeScrollWindow(cm, rect) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) { + return; + } + + var display = cm.display, + box = display.sizer.getBoundingClientRect(), + doScroll = null; + + if (rect.top + box.top < 0) { + doScroll = true; + } else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { + doScroll = false; + } + + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200B", null, "position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + rect.left + "px; width: " + Math.max(2, rect.right - rect.left) + "px;"); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + + + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) { + margin = 0; + } + + var rect; + + if (!cm.options.lineWrapping && pos == end) { + // Set pos and end to the cursor positions around the character pos sticks to + // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch + // If pos == Pos(_, 0, "before"), pos and end are unchanged + pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; + end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; + } + + for (var limit = 0; limit < 5; limit++) { + var changed = false; + + var coords = _cursorCoords(cm, pos); + + var endCoords = !end || end == pos ? coords : _cursorCoords(cm, end); + rect = { + left: Math.min(coords.left, endCoords.left), + top: Math.min(coords.top, endCoords.top) - margin, + right: Math.max(coords.left, endCoords.left), + bottom: Math.max(coords.bottom, endCoords.bottom) + margin + }; + var scrollPos = calculateScrollPos(cm, rect); + var startTop = cm.doc.scrollTop, + startLeft = cm.doc.scrollLeft; + + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop); + + if (Math.abs(cm.doc.scrollTop - startTop) > 1) { + changed = true; + } + } + + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { + changed = true; + } + } + + if (!changed) { + break; + } + } + + return rect; + } // Scroll a given set of coordinates into view (immediately). + + + function scrollIntoView(cm, rect) { + var scrollPos = calculateScrollPos(cm, rect); + + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop); + } + + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + } + } // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + + + function calculateScrollPos(cm, rect) { + var display = cm.display, + snapMargin = textHeight(cm.display); + + if (rect.top < 0) { + rect.top = 0; + } + + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), + result = {}; + + if (rect.bottom - rect.top > screen) { + rect.bottom = rect.top + screen; + } + + var docBottom = cm.doc.height + paddingVert(display); + var atTop = rect.top < snapMargin, + atBottom = rect.bottom > docBottom - snapMargin; + + if (rect.top < screentop) { + result.scrollTop = atTop ? 0 : rect.top; + } else if (rect.bottom > screentop + screen) { + var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); + + if (newTop != screentop) { + result.scrollTop = newTop; + } + } + + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; + var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); + var tooWide = rect.right - rect.left > screenw; + + if (tooWide) { + rect.right = rect.left + screenw; + } + + if (rect.left < 10) { + result.scrollLeft = 0; + } else if (rect.left < screenleft) { + result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); + } else if (rect.right > screenw + screenleft - 3) { + result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; + } + + return result; + } // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + + + function addToScrollTop(cm, top) { + if (top == null) { + return; + } + + resolveScrollToPos(cm); + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } // Make sure that at the end of the operation the current cursor is + // shown. + + + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(); + cm.curOp.scrollToPos = { + from: cur, + to: cur, + margin: cm.options.cursorScrollMargin + }; + } + + function scrollToCoords(cm, x, y) { + if (x != null || y != null) { + resolveScrollToPos(cm); + } + + if (x != null) { + cm.curOp.scrollLeft = x; + } + + if (y != null) { + cm.curOp.scrollTop = y; + } + } + + function scrollToRange(cm, range$$1) { + resolveScrollToPos(cm); + cm.curOp.scrollToPos = range$$1; + } // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + + + function resolveScrollToPos(cm) { + var range$$1 = cm.curOp.scrollToPos; + + if (range$$1) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range$$1.from), + to = estimateCoords(cm, range$$1.to); + scrollToCoordsRange(cm, from, to, range$$1.margin); + } + } + + function scrollToCoordsRange(cm, from, to, margin) { + var sPos = calculateScrollPos(cm, { + left: Math.min(from.left, to.left), + top: Math.min(from.top, to.top) - margin, + right: Math.max(from.right, to.right), + bottom: Math.max(from.bottom, to.bottom) + margin + }); + scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); + } // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + + + function updateScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) { + return; + } + + if (!gecko) { + updateDisplaySimple(cm, { + top: val + }); + } + + setScrollTop(cm, val, true); + + if (gecko) { + updateDisplaySimple(cm); + } + + startWorker(cm, 100); + } + + function setScrollTop(cm, val, forceScroll) { + val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val); + + if (cm.display.scroller.scrollTop == val && !forceScroll) { + return; + } + + cm.doc.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + + if (cm.display.scroller.scrollTop != val) { + cm.display.scroller.scrollTop = val; + } + } // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + + + function setScrollLeft(cm, val, isScroller, forceScroll) { + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + + if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { + return; + } + + cm.doc.scrollLeft = val; + alignHorizontally(cm); + + if (cm.display.scroller.scrollLeft != val) { + cm.display.scroller.scrollLeft = val; + } + + cm.display.scrollbars.setScrollLeft(val); + } // SCROLLBARS + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + + + function measureForScrollbars(cm) { + var d = cm.display, + gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, + clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + }; + } + + var NativeScrollbars = function NativeScrollbars(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + vert.tabIndex = horiz.tabIndex = -1; + place(vert); + place(horiz); + on(vert, "scroll", function () { + if (vert.clientHeight) { + scroll(vert.scrollTop, "vertical"); + } + }); + on(horiz, "scroll", function () { + if (horiz.clientWidth) { + scroll(horiz.scrollLeft, "horizontal"); + } + }); + this.checkedZeroWidth = false; // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + + if (ie && ie_version < 8) { + this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; + } + }; + + NativeScrollbars.prototype.update = function (measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); // A bug in IE8 can cause this value to be negative, so guard it. + + this.vert.firstChild.style.height = Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) { + this.zeroWidthHack(); + } + + this.checkedZeroWidth = true; + } + + return { + right: needsV ? sWidth : 0, + bottom: needsH ? sWidth : 0 + }; + }; + + NativeScrollbars.prototype.setScrollLeft = function (pos) { + if (this.horiz.scrollLeft != pos) { + this.horiz.scrollLeft = pos; + } + + if (this.disableHoriz) { + this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); + } + }; + + NativeScrollbars.prototype.setScrollTop = function (pos) { + if (this.vert.scrollTop != pos) { + this.vert.scrollTop = pos; + } + + if (this.disableVert) { + this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); + } + }; + + NativeScrollbars.prototype.zeroWidthHack = function () { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; + this.disableHoriz = new Delayed(); + this.disableVert = new Delayed(); + }; + + NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { + bar.style.pointerEvents = "auto"; + + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // right corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt$$1 = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); + + if (elt$$1 != bar) { + bar.style.pointerEvents = "none"; + } else { + delay.set(1000, maybeDisable); + } + } + + delay.set(1000, maybeDisable); + }; + + NativeScrollbars.prototype.clear = function () { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + }; + + var NullScrollbars = function NullScrollbars() {}; + + NullScrollbars.prototype.update = function () { + return { + bottom: 0, + right: 0 + }; + }; + + NullScrollbars.prototype.setScrollLeft = function () {}; + + NullScrollbars.prototype.setScrollTop = function () {}; + + NullScrollbars.prototype.clear = function () {}; + + function updateScrollbars(cm, measure) { + if (!measure) { + measure = measureForScrollbars(cm); + } + + var startWidth = cm.display.barWidth, + startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) { + updateHeightsInViewport(cm); + } + + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; + startHeight = cm.display.barHeight; + } + } // Re-synchronize the fake scrollbars with the actual size of the + // content. + + + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else { + d.scrollbarFiller.style.display = ""; + } + + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else { + d.gutterFiller.style.display = ""; + } + } + + var scrollbarModel = { + "native": NativeScrollbars, + "null": NullScrollbars + }; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + + if (cm.display.scrollbars.addClass) { + rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + } + + cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); // Prevent clicks in the scrollbars from killing focus + + on(node, "mousedown", function () { + if (cm.state.focused) { + setTimeout(function () { + return cm.display.input.focus(); + }, 0); + } + }); + node.setAttribute("cm-not-content", "true"); + }, function (pos, axis) { + if (axis == "horizontal") { + setScrollLeft(cm, pos); + } else { + updateScrollTop(cm, pos); + } + }, cm); + + if (cm.display.scrollbars.addClass) { + addClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + } // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + + var nextOpId = 0; // Start a new operation. + + function _startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, + // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, + // Used to detect need to update scrollbar + forceUpdate: false, + // Used to force a redraw + updateInput: 0, + // Whether to reset the input textarea + typing: false, + // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, + // Accumulated changes, for firing change events + cursorActivityHandlers: null, + // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, + // Tracks which cursorActivity handlers have been called already + selectionChanged: false, + // Whether the selection needs to be redrawn + updateMaxLine: false, + // Set when the widest line needs to be determined anew + scrollLeft: null, + scrollTop: null, + // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, + // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + + }; + pushOperation(cm.curOp); + } // Finish an operation, updating the display and signalling delayed events + + + function _endOperation(cm) { + var op = cm.curOp; + + if (op) { + finishOperation(op, function (group) { + for (var i = 0; i < group.ops.length; i++) { + group.ops[i].cm.curOp = null; + } + + endOperations(group); + }); + } + } // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + + + function endOperations(group) { + var ops = group.ops; + + for (var i = 0; i < ops.length; i++) // Read DOM + { + endOperation_R1(ops[i]); + } + + for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) + { + endOperation_W1(ops[i$1]); + } + + for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM + { + endOperation_R2(ops[i$2]); + } + + for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) + { + endOperation_W2(ops[i$3]); + } + + for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM + { + endOperation_finish(ops[i$4]); + } + } + + function endOperation_R1(op) { + var cm = op.cm, + display = cm.display; + maybeClipScrollbars(cm); + + if (op.updateMaxLine) { + findMaxLine(cm); + } + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || op.scrollToPos.to.line >= display.viewTo) || display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && new DisplayUpdate(cm, op.mustUpdate && { + top: op.scrollTop, + ensure: op.scrollToPos + }, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, + display = cm.display; + + if (op.updatedDisplay) { + updateHeightsInViewport(cm); + } + + op.barMeasure = measureForScrollbars(cm); // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) { + op.preparedSelection = display.input.prepareSelection(); + } + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + + if (op.maxScrollLeft < cm.doc.scrollLeft) { + setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); + } + + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt(); + + if (op.preparedSelection) { + cm.display.input.showSelection(op.preparedSelection, takeFocus); + } + + if (op.updatedDisplay || op.startHeight != cm.doc.height) { + updateScrollbars(cm, op.barMeasure); + } + + if (op.updatedDisplay) { + setDocumentHeight(cm, op.barMeasure); + } + + if (op.selectionChanged) { + restartBlink(cm); + } + + if (cm.state.focused && op.updateInput) { + cm.display.input.reset(op.typing); + } + + if (takeFocus) { + ensureFocus(op.cm); + } + } + + function endOperation_finish(op) { + var cm = op.cm, + display = cm.display, + doc = cm.doc; + + if (op.updatedDisplay) { + postUpdateDisplay(cm, op.update); + } // Abort mouse wheel delta measurement, when scrolling explicitly + + + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) { + display.wheelStartX = display.wheelStartY = null; + } // Propagate the scroll position to the actual DOM scroller + + + if (op.scrollTop != null) { + setScrollTop(cm, op.scrollTop, op.forceScroll); + } + + if (op.scrollLeft != null) { + setScrollLeft(cm, op.scrollLeft, true, true); + } // If we need to scroll a specific position into view, do so. + + + if (op.scrollToPos) { + var rect = scrollPosIntoView(cm, _clipPos(doc, op.scrollToPos.from), _clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + maybeScrollWindow(cm, rect); + } // Fire events for markers that are hidden/unidden by editing or + // undoing + + + var hidden = op.maybeHiddenMarkers, + unhidden = op.maybeUnhiddenMarkers; + + if (hidden) { + for (var i = 0; i < hidden.length; ++i) { + if (!hidden[i].lines.length) { + signal(hidden[i], "hide"); + } + } + } + + if (unhidden) { + for (var i$1 = 0; i$1 < unhidden.length; ++i$1) { + if (unhidden[i$1].lines.length) { + signal(unhidden[i$1], "unhide"); + } + } + } + + if (display.wrapper.offsetHeight) { + doc.scrollTop = cm.display.scroller.scrollTop; + } // Fire change events, and delayed event handlers + + + if (op.changeObjs) { + signal(cm, "changes", cm, op.changeObjs); + } + + if (op.update) { + op.update.finish(); + } + } // Run the given function in an operation + + + function runInOp(cm, f) { + if (cm.curOp) { + return f(); + } + + _startOperation(cm); + + try { + return f(); + } finally { + _endOperation(cm); + } + } // Wraps a function in an operation. Returns the wrapped function. + + + function operation(cm, f) { + return function () { + if (cm.curOp) { + return f.apply(cm, arguments); + } + + _startOperation(cm); + + try { + return f.apply(cm, arguments); + } finally { + _endOperation(cm); + } + }; + } // Used to add methods to editor and doc instances, wrapping them in + // operations. + + + function methodOp(f) { + return function () { + if (this.curOp) { + return f.apply(this, arguments); + } + + _startOperation(this); + + try { + return f.apply(this, arguments); + } finally { + _endOperation(this); + } + }; + } + + function docMethodOp(f) { + return function () { + var cm = this.cm; + + if (!cm || cm.curOp) { + return f.apply(this, arguments); + } + + _startOperation(cm); + + try { + return f.apply(this, arguments); + } finally { + _endOperation(cm); + } + }; + } // HIGHLIGHT WORKER + + + function startWorker(cm, time) { + if (cm.doc.highlightFrontier < cm.display.viewTo) { + cm.state.highlight.set(time, bind(highlightWorker, cm)); + } + } + + function highlightWorker(cm) { + var doc = cm.doc; + + if (doc.highlightFrontier >= cm.display.viewTo) { + return; + } + + var end = +new Date() + cm.options.workTime; + var context = getContextBefore(cm, doc.highlightFrontier); + var changedLines = []; + doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { + if (context.line >= cm.display.viewFrom) { + // Visible + var oldStyles = line.styles; + var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; + var highlighted = highlightLine(cm, line, context, true); + + if (resetState) { + context.state = resetState; + } + + line.styles = highlighted.styles; + var oldCls = line.styleClasses, + newCls = highlighted.classes; + + if (newCls) { + line.styleClasses = newCls; + } else if (oldCls) { + line.styleClasses = null; + } + + var ischange = !oldStyles || oldStyles.length != line.styles.length || oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + + for (var i = 0; !ischange && i < oldStyles.length; ++i) { + ischange = oldStyles[i] != line.styles[i]; + } + + if (ischange) { + changedLines.push(context.line); + } + + line.stateAfter = context.save(); + context.nextLine(); + } else { + if (line.text.length <= cm.options.maxHighlightLength) { + processLine(cm, line.text, context); + } + + line.stateAfter = context.line % 5 == 0 ? context.save() : null; + context.nextLine(); + } + + if (+new Date() > end) { + startWorker(cm, cm.options.workDelay); + return true; + } + }); + doc.highlightFrontier = context.line; + doc.modeFrontier = Math.max(doc.modeFrontier, context.line); + + if (changedLines.length) { + runInOp(cm, function () { + for (var i = 0; i < changedLines.length; i++) { + regLineChange(cm, changedLines[i], "text"); + } + }); + } + } // DISPLAY DRAWING + + + var DisplayUpdate = function DisplayUpdate(cm, viewport, force) { + var display = cm.display; + this.viewport = viewport; // Store some values that we'll need later (but don't want to force a relayout for) + + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + }; + + DisplayUpdate.prototype.signal = function (emitter, type) { + if (hasHandler(emitter, type)) { + this.events.push(arguments); + } + }; + + DisplayUpdate.prototype.finish = function () { + var this$1 = this; + + for (var i = 0; i < this.events.length; i++) { + signal.apply(null, this$1.events[i]); + } + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + function selectionSnapshot(cm) { + if (cm.hasFocus()) { + return null; + } + + var active = activeElt(); + + if (!active || !contains(cm.display.lineDiv, active)) { + return null; + } + + var result = { + activeElt: active + }; + + if (window.getSelection) { + var sel = window.getSelection(); + + if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { + result.anchorNode = sel.anchorNode; + result.anchorOffset = sel.anchorOffset; + result.focusNode = sel.focusNode; + result.focusOffset = sel.focusOffset; + } + } + + return result; + } + + function restoreSelection(snapshot) { + if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { + return; + } + + snapshot.activeElt.focus(); + + if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + var sel = window.getSelection(), + range$$1 = document.createRange(); + range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset); + range$$1.collapse(false); + sel.removeAllRanges(); + sel.addRange(range$$1); + sel.extend(snapshot.focusNode, snapshot.focusOffset); + } + } // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + + + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, + doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false; + } // Bail out if the visible area is already rendered and nothing changed. + + + if (!update.force && update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && display.renderedView == display.view && countDirtyView(cm) == 0) { + return false; + } + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } // Compute a suitable new viewport (from & to) + + + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + + if (display.viewFrom < from && from - display.viewFrom < 20) { + from = Math.max(doc.first, display.viewFrom); + } + + if (display.viewTo > to && display.viewTo - to < 20) { + to = Math.min(end, display.viewTo); + } + + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + display.viewOffset = _heightAtLine(getLine(cm.doc, display.viewFrom)); // Position the mover div to align with the current scroll position + + cm.display.mover.style.top = display.viewOffset + "px"; + var toUpdate = countDirtyView(cm); + + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) { + return false; + } // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + + + var selSnapshot = selectionSnapshot(cm); + + if (toUpdate > 4) { + display.lineDiv.style.display = "none"; + } + + patchDisplay(cm, display.updateLineNumbers, update.dims); + + if (toUpdate > 4) { + display.lineDiv.style.display = ""; + } + + display.renderedView = display.view; // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + + restoreSelection(selSnapshot); // Prevent selection and cursors from interfering with the scroll + // width and height. + + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + return true; + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) { + viewport = { + top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top) + }; + } // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + + + update.visible = visibleLines(cm.display, cm.doc, viewport); + + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) { + break; + } + } + + if (!updateDisplayIfNeeded(cm, update)) { + break; + } + + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.force = false; + } + + update.signal(cm, "update", cm); + + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; + cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + + + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, + lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, + cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; // Works around a throw-scroll bug in OS X Webkit + + if (webkit && mac && cm.display.currentWheelTarget == node) { + node.style.display = "none"; + } else { + node.parentNode.removeChild(node); + } + + return next; + } + + var view = display.view, + lineN = display.viewFrom; // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) ;else if (!lineView.node || lineView.node.parentNode != container) { + // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { + // Already drawn + while (cur != lineView.node) { + cur = rm(cur); + } + + var updateNumber = lineNumbers && updateNumbersFrom != null && updateNumbersFrom <= lineN && lineView.lineNumber; + + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) { + updateNumber = false; + } + + updateLineForChanges(cm, lineView, lineN, dims); + } + + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + + while (cur) { + cur = rm(cur); + } + } + + function updateGutterSpace(display) { + var width = display.gutters.offsetWidth; + display.sizer.style.marginLeft = width + "px"; + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = measure.docHeight + cm.display.barHeight + scrollGap(cm) + "px"; + } // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + + + function alignHorizontally(cm) { + var display = cm.display, + view = display.view; + + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { + return; + } + + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, + left = comp + "px"; + + for (var i = 0; i < view.length; i++) { + if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) { + view[i].gutter.style.left = left; + } + + if (view[i].gutterBackground) { + view[i].gutterBackground.style.left = left; + } + } + + var align = view[i].alignable; + + if (align) { + for (var j = 0; j < align.length; j++) { + align[j].style.left = left; + } + } + } + } + + if (cm.options.fixedGutter) { + display.gutters.style.left = comp + gutterW + "px"; + } + } // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + + + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { + return false; + } + + var doc = cm.doc, + last = lineNumberFor(cm.options, doc.first + doc.size - 1), + display = cm.display; + + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, + padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm.display); + return true; + } + + return false; + } + + function getGutters(gutters, lineNumbers) { + var result = [], + sawLineNumbers = false; + + for (var i = 0; i < gutters.length; i++) { + var name = gutters[i], + style = null; + + if (typeof name != "string") { + style = name.style; + name = name.className; + } + + if (name == "CodeMirror-linenumbers") { + if (!lineNumbers) { + continue; + } else { + sawLineNumbers = true; + } + } + + result.push({ + className: name, + style: style + }); + } + + if (lineNumbers && !sawLineNumbers) { + result.push({ + className: "CodeMirror-linenumbers", + style: null + }); + } + + return result; + } // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + + + function renderGutters(display) { + var gutters = display.gutters, + specs = display.gutterSpecs; + removeChildren(gutters); + display.lineGutter = null; + + for (var i = 0; i < specs.length; ++i) { + var ref = specs[i]; + var className = ref.className; + var style = ref.style; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); + + if (style) { + gElt.style.cssText = style; + } + + if (className == "CodeMirror-linenumbers") { + display.lineGutter = gElt; + gElt.style.width = (display.lineNumWidth || 1) + "px"; + } + } + + gutters.style.display = specs.length ? "" : "none"; + updateGutterSpace(display); + } + + function updateGutters(cm) { + renderGutters(cm.display); + regChange(cm); + alignHorizontally(cm); + } // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + + function Display(place, doc, input, options) { + var d = this; + this.input = input; // Covers bottom-right square when both scrollbars are present. + + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); // Will contain the actual code, positioned to cover the viewport. + + d.lineDiv = eltP("div", null, "CodeMirror-code"); // Elements are added to these to represent selection and cursors. + + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); // A visibility: hidden element used to find the size of things. + + d.measure = elt("div", null, "CodeMirror-measure"); // When lines outside of the viewport are measured, they are drawn in this. + + d.lineMeasure = elt("div", null, "CodeMirror-measure"); // Wraps everything that needs to exist inside the vertically-padded coordinate system + + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], null, "position: relative; outline: none"); + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); // Moved around its parent to cover visible view. + + d.mover = elt("div", [lines], null, "position: relative"); // Set to the height of the document, allowing scrolling. + + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); // Will contain the gutters, if any. + + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; // Actual scrollable element. + + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); // The element in which the editor lives. + + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + + if (ie && ie_version < 8) { + d.gutters.style.zIndex = -1; + d.scroller.style.paddingRight = 0; + } + + if (!webkit && !(gecko && mobile)) { + d.scroller.draggable = true; + } + + if (place) { + if (place.appendChild) { + place.appendChild(d.wrapper); + } else { + place(d.wrapper); + } + } // Current rendered range (may be bigger than the view window). + + + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; // Information about the rendered lines. + + d.view = []; + d.renderedView = null; // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + + d.externalMeasured = null; // Empty space (in pixels) above the view + + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + + d.alignWidgets = false; + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; // Used for measuring wheel scrolling granularity + + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; // True when shift is held down. + + d.shift = false; // Used to track whether anything happened since the context menu + // was opened. + + d.selForContextMenu = null; + d.activeTouch = null; + d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); + renderGutters(d); + input.init(d); + } // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + + var wheelSamples = 0, + wheelPixelsPerUnit = null; // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + + if (ie) { + wheelPixelsPerUnit = -.53; + } else if (gecko) { + wheelPixelsPerUnit = 15; + } else if (chrome) { + wheelPixelsPerUnit = -.7; + } else if (safari) { + wheelPixelsPerUnit = -1 / 3; + } + + function wheelEventDelta(e) { + var dx = e.wheelDeltaX, + dy = e.wheelDeltaY; + + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { + dx = e.detail; + } + + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { + dy = e.detail; + } else if (dy == null) { + dy = e.wheelDelta; + } + + return { + x: dx, + y: dy + }; + } + + function wheelEventPixels(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta; + } + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), + dx = delta.x, + dy = delta.y; + var display = cm.display, + scroll = display.scroller; // Quit if there's nothing to scroll here + + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + + if (!(dx && canScrollX || dy && canScrollY)) { + return; + } // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + + + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer; + } + } + } + } // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + + + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) { + updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); + } + + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + + if (!dy || dy && canScrollY) { + e_preventDefault(e); + } + + display.wheelStartX = null; // Abort measurement, if in progress + + return; + } // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + + + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, + bot = top + display.wrapper.clientHeight; + + if (pixels < 0) { + top = Math.max(0, top + pixels - 50); + } else { + bot = Math.min(cm.doc.height, bot + pixels + 50); + } + + updateDisplaySimple(cm, { + top: top, + bottom: bot + }); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; + display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; + display.wheelDY = dy; + setTimeout(function () { + if (display.wheelStartX == null) { + return; + } + + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = movedY && display.wheelDY && movedY / display.wheelDY || movedX && display.wheelDX && movedX / display.wheelDX; + display.wheelStartX = display.wheelStartY = null; + + if (!sample) { + return; + } + + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; + display.wheelDY += dy; + } + } + } // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + + + var Selection = function Selection(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + }; + + Selection.prototype.primary = function () { + return this.ranges[this.primIndex]; + }; + + Selection.prototype.equals = function (other) { + var this$1 = this; + + if (other == this) { + return true; + } + + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { + return false; + } + + for (var i = 0; i < this.ranges.length; i++) { + var here = this$1.ranges[i], + there = other.ranges[i]; + + if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { + return false; + } + } + + return true; + }; + + Selection.prototype.deepCopy = function () { + var this$1 = this; + var out = []; + + for (var i = 0; i < this.ranges.length; i++) { + out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); + } + + return new Selection(out, this.primIndex); + }; + + Selection.prototype.somethingSelected = function () { + var this$1 = this; + + for (var i = 0; i < this.ranges.length; i++) { + if (!this$1.ranges[i].empty()) { + return true; + } + } + + return false; + }; + + Selection.prototype.contains = function (pos, end) { + var this$1 = this; + + if (!end) { + end = pos; + } + + for (var i = 0; i < this.ranges.length; i++) { + var range = this$1.ranges[i]; + + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) { + return i; + } + } + + return -1; + }; + + var Range = function Range(anchor, head) { + this.anchor = anchor; + this.head = head; + }; + + Range.prototype.from = function () { + return minPos(this.anchor, this.head); + }; + + Range.prototype.to = function () { + return maxPos(this.anchor, this.head); + }; + + Range.prototype.empty = function () { + return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; + }; // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + + + function normalizeSelection(cm, ranges, primIndex) { + var mayTouch = cm && cm.options.selectionsMayTouch; + var prim = ranges[primIndex]; + ranges.sort(function (a, b) { + return cmp(a.from(), b.from()); + }); + primIndex = indexOf(ranges, prim); + + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], + prev = ranges[i - 1]; + var diff = cmp(prev.to(), cur.from()); + + if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { + var from = minPos(prev.from(), cur.from()), + to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + + if (i <= primIndex) { + --primIndex; + } + + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + + return new Selection(ranges, primIndex); + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0); + } // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + + + function changeEnd(change) { + if (!change.text) { + return change.to; + } + + return Pos(change.from.line + change.text.length - 1, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); + } // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + + + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) { + return pos; + } + + if (cmp(pos, change.to) <= 0) { + return changeEnd(change); + } + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, + ch = pos.ch; + + if (pos.line == change.to.line) { + ch += changeEnd(change).ch - change.to.ch; + } + + return Pos(line, ch); + } + + function computeSelAfterChange(doc, change) { + var out = []; + + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), adjustForChange(range.head, change))); + } + + return normalizeSelection(doc.cm, out, doc.sel.primIndex); + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) { + return Pos(nw.line, pos.ch - old.ch + nw.ch); + } else { + return Pos(nw.line + (pos.line - old.line), pos.ch); + } + } // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + + + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), + newPrev = oldPrev; + + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + + if (hint == "around") { + var range = doc.sel.ranges[i], + inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + + return new Selection(out, doc.sel.primIndex); + } // Used to get the editor into a consistent state again when options change. + + + function loadMode(cm) { + cm.doc.mode = getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function (line) { + if (line.stateAfter) { + line.stateAfter = null; + } + + if (line.styles) { + line.styles = null; + } + }); + cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + + if (cm.curOp) { + regChange(cm); + } + } // DOCUMENT DATA STRUCTURE + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + + + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && (!doc.cm || doc.cm.options.wholeLineUpdateBefore); + } // Perform a change on the document data structure. + + + function updateDoc(doc, change, markedSpans, estimateHeight$$1) { + function spansFor(n) { + return markedSpans ? markedSpans[n] : null; + } + + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight$$1); + signalLater(line, "change", line, change); + } + + function linesFor(start, end) { + var result = []; + + for (var i = start; i < end; ++i) { + result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); + } + + return result; + } + + var from = change.from, + to = change.to, + text = change.text; + var firstLine = getLine(doc, from.line), + lastLine = getLine(doc, to.line); + var lastText = lst(text), + lastSpans = spansFor(text.length - 1), + nlines = to.line - from.line; // Adjust the line structure + + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + + if (nlines) { + doc.remove(from.line, nlines); + } + + if (added.length) { + doc.insert(from.line, added); + } + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added$1 = linesFor(1, text.length - 1); + added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added$1); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added$2 = linesFor(1, text.length - 1); + + if (nlines > 1) { + doc.remove(from.line + 1, nlines - 1); + } + + doc.insert(from.line + 1, added$2); + } + + signalLater(doc, "change", doc, change); + } // Call f for all linked documents. + + + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) { + for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + + if (rel.doc == skip) { + continue; + } + + var shared = sharedHist && rel.sharedHist; + + if (sharedHistOnly && !shared) { + continue; + } + + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } + } + } + + propagate(doc, null, true); + } // Attach a document to an editor. + + + function attachDoc(cm, doc) { + if (doc.cm) { + throw new Error("This document is already in use."); + } + + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + setDirectionClass(cm); + + if (!cm.options.lineWrapping) { + findMaxLine(cm); + } + + cm.options.mode = doc.modeOption; + regChange(cm); + } + + function setDirectionClass(cm) { + (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); + } + + function directionChanged(cm) { + runInOp(cm, function () { + setDirectionClass(cm); + regChange(cm); + }); + } + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; + this.undone = []; + this.undoDepth = Infinity; // Used to track when changes can be merged into a single undo + // event + + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; // Used by the isClean() method + + this.generation = this.maxGeneration = startGen || 1; + } // Create a history change event from an updateDoc-style change + // object. + + + function historyChangeFromChange(doc, change) { + var histChange = { + from: copyPos(change.from), + to: changeEnd(change), + text: getBetween(doc, change.from, change.to) + }; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function (doc) { + return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + }, true); + return histChange; + } // Pop all selection events off the end of a history array. Stop at + // a change event. + + + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + + if (last.ranges) { + array.pop(); + } else { + break; + } + } + } // Find the top change event in the history. Pop off selection + // events that are in the way. + + + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done); + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done); + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done); + } + } // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + + + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date(), + cur; + var last; + + if ((hist.lastOp == opId || hist.lastOrigin == change.origin && change.origin && (change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500) || change.origin.charAt(0) == "*")) && (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + last = lst(cur.changes); + + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + + if (!before || !before.ranges) { + pushSelectionToHistory(doc.sel, hist.done); + } + + cur = { + changes: [historyChangeFromChange(doc, change)], + generation: hist.generation + }; + hist.done.push(cur); + + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + + if (!hist.done[0].ranges) { + hist.done.shift(); + } + } + } + + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) { + signal(doc, "historyAdded"); + } + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || ch == "+" && prev.ranges.length == sel.ranges.length && prev.somethingSelected() == sel.somethingSelected() && new Date() - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); + } // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + + + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, + origin = options && options.origin; // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + + if (opId == hist.lastSelOp || origin && hist.lastSelOrigin == origin && (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))) { + hist.done[hist.done.length - 1] = sel; + } else { + pushSelectionToHistory(sel, hist.done); + } + + hist.lastSelTime = +new Date(); + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + + if (options && options.clearRedo !== false) { + clearSelectionEvents(hist.undone); + } + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + + if (!(top && top.ranges && top.equals(sel))) { + dest.push(sel); + } + } // Used to store marked span information in the history. + + + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], + n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { + if (line.markedSpans) { + (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; + } + + ++n; + }); + } // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + + + function removeClearedSpans(spans) { + if (!spans) { + return null; + } + + var out; + + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { + if (!out) { + out = spans.slice(0, i); + } + } else if (out) { + out.push(spans[i]); + } + } + + return !out ? spans : out.length ? out : null; + } // Retrieve and filter the old marked spans stored in a change event. + + + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + + if (!found) { + return null; + } + + var nw = []; + + for (var i = 0; i < change.text.length; ++i) { + nw.push(removeClearedSpans(found[i])); + } + + return nw; + } // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + + + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + + if (!old) { + return stretched; + } + + if (!stretched) { + return old; + } + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], + stretchCur = stretched[i]; + + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + + for (var k = 0; k < oldCur.length; ++k) { + if (oldCur[k].marker == span.marker) { + continue spans; + } + } + + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + + return old; + } // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + + + function copyHistoryArray(events, newGroup, instantiateSel) { + var copy = []; + + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue; + } + + var changes = event.changes, + newChanges = []; + copy.push({ + changes: newChanges + }); + + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], + m = void 0; + newChanges.push({ + from: change.from, + to: change.to, + text: change.text + }); + + if (newGroup) { + for (var prop in change) { + if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } + } + } + } + } + + return copy; + } // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + + + function extendRange(range, head, other, extend) { + if (extend) { + var anchor = range.anchor; + + if (other) { + var posBefore = cmp(head, anchor) < 0; + + if (posBefore != cmp(other, anchor) < 0) { + anchor = head; + head = other; + } else if (posBefore != cmp(head, other) < 0) { + head = other; + } + } + + return new Range(anchor, head); + } else { + return new Range(other || head, head); + } + } // Extend the primary selection range, discard the rest. + + + function extendSelection(doc, head, other, options, extend) { + if (extend == null) { + extend = doc.cm && (doc.cm.display.shift || doc.extend); + } + + setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); + } // Extend all selections (pos is an array of selections with length + // equal the number of selections) + + + function extendSelections(doc, heads, options) { + var out = []; + var extend = doc.cm && (doc.cm.display.shift || doc.extend); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); + } + + var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } // Updates a single range in the selection. + + + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); + } // Reset the selection to a single range. + + + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } // Give beforeSelectionChange handlers a change to influence a + // selection update. + + + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function update(ranges) { + var this$1 = this; + this.ranges = []; + + for (var i = 0; i < ranges.length; i++) { + this$1.ranges[i] = new Range(_clipPos(doc, ranges[i].anchor), _clipPos(doc, ranges[i].head)); + } + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + + if (doc.cm) { + signal(doc.cm, "beforeSelectionChange", doc.cm, obj); + } + + if (obj.ranges != sel.ranges) { + return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1); + } else { + return sel; + } + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, + last = lst(done); + + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } // Set a new selection. + + + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) { + sel = filterSelectionChange(doc, sel, options); + } + + var bias = options && options.bias || (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm) { + ensureCursorVisible(doc.cm); + } + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) { + return; + } + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = 1; + doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + + signalLater(doc, "cursorActivity", doc); + } // Verify that the selection does not partially select any atomic + // marked ranges. + + + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); + } // Return a selection that does not partially select any atomic + // ranges. + + + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); + + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) { + out = sel.ranges.slice(0, i); + } + + out[i] = new Range(newAnchor, newHead); + } + } + + return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel; + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + + if (line.markedSpans) { + for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], + m = sp.marker; // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + + var preventCursorLeft = "selectLeft" in m ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = "selectRight" in m ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + + if (m.explicitlyCleared) { + if (!line.markedSpans) { + break; + } else { + --i; + continue; + } + } + } + + if (!m.atomic) { + continue; + } + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), + diff = void 0; + + if (dir < 0 ? preventCursorRight : preventCursorLeft) { + near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); + } + + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) { + return skipAtomicInner(doc, near, pos, dir, mayClear); + } + } + + var far = m.find(dir < 0 ? -1 : 1); + + if (dir < 0 ? preventCursorLeft : preventCursorRight) { + far = movePos(doc, far, dir, far.line == pos.line ? line : null); + } + + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null; + } + } + } + + return pos; + } // Ensure a given position is not inside an atomic range. + + + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || !mayClear && skipAtomicInner(doc, pos, oldPos, dir, true) || skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || !mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true); + + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0); + } + + return found; + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) { + return _clipPos(doc, Pos(pos.line - 1)); + } else { + return null; + } + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) { + return Pos(pos.line + 1, 0); + } else { + return null; + } + } else { + return new Pos(pos.line, pos.ch + dir); + } + } + + function selectAll(cm) { + cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); + } // UPDATING + // Allow "beforeChange" event handlers to influence a change + + + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function cancel() { + return obj.canceled = true; + } + }; + + if (update) { + obj.update = function (from, to, text, origin) { + if (from) { + obj.from = _clipPos(doc, from); + } + + if (to) { + obj.to = _clipPos(doc, to); + } + + if (text) { + obj.text = text; + } + + if (origin !== undefined) { + obj.origin = origin; + } + }; + } + + signal(doc, "beforeChange", doc, obj); + + if (doc.cm) { + signal(doc.cm, "beforeChange", doc.cm, obj); + } + + if (obj.canceled) { + if (doc.cm) { + doc.cm.curOp.updateInput = 2; + } + + return null; + } + + return { + from: obj.from, + to: obj.to, + text: obj.text, + origin: obj.origin + }; + } // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + + + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) { + return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); + } + + if (doc.cm.state.suppressEdits) { + return; + } + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + + if (!change) { + return; + } + } // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + + + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + + if (split) { + for (var i = split.length - 1; i >= 0; --i) { + makeChangeInner(doc, { + from: split[i].from, + to: split[i].to, + text: i ? [""] : change.text, + origin: change.origin + }); + } + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { + return; + } + + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } // Revert a change stored in a document's history. + + + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + var suppress = doc.cm && doc.cm.state.suppressEdits; + + if (suppress && !allowSelectionOnly) { + return; + } + + var hist = doc.history, + event, + selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, + dest = type == "undo" ? hist.undone : hist.done; // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + + var i = 0; + + for (; i < source.length; i++) { + event = source[i]; + + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) { + break; + } + } + + if (i == source.length) { + return; + } + + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + + if (event.ranges) { + pushSelectionToHistory(event, dest); + + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, { + clearRedo: false + }); + return; + } + + selAfter = event; + } else if (suppress) { + source.push(event); + return; + } else { + break; + } + } // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + + + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({ + changes: antiChanges, + generation: hist.generation + }); + hist.generation = event.generation || ++hist.maxGeneration; + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + var loop = function loop(i) { + var change = event.changes[i]; + change.origin = type; + + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return {}; + } + + antiChanges.push(historyChangeFromChange(doc, change)); + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + + if (!i && doc.cm) { + doc.cm.scrollIntoView({ + from: change.from, + to: changeEnd(change) + }); + } + + var rebased = []; // Propagate to the linked documents + + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + }; + + for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { + var returned = loop(i$1); + if (returned) return returned.v; + } + } // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + + + function shiftDoc(doc, distance) { + if (distance == 0) { + return; + } + + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function (range) { + return new Range(Pos(range.anchor.line + distance, range.anchor.ch), Pos(range.head.line + distance, range.head.ch)); + }), doc.sel.primIndex); + + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) { + regLineChange(doc.cm, l, "gutter"); + } + } + } // More lower-level change function, handling only a single document + // (not linked ones). + + + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) { + return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); + } + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return; + } + + if (change.from.line > doc.lastLine()) { + return; + } // Clip the change to the size of this doc + + + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = { + from: Pos(doc.first, 0), + to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], + origin: change.origin + }; + } + + var last = doc.lastLine(); + + if (change.to.line > last) { + change = { + from: change.from, + to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], + origin: change.origin + }; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) { + selAfter = computeSelAfterChange(doc, change); + } + + if (doc.cm) { + makeChangeSingleDocInEditor(doc.cm, change, spans); + } else { + updateDoc(doc, change, spans); + } + + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + + if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) { + doc.cantEdit = false; + } + } // Handle the interaction of a change to a document with the editor + // that this document is part of. + + + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, + display = cm.display, + from = change.from, + to = change.to; + var recomputeMaxLength = false, + checkWidthStart = from.line; + + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function (line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true; + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) { + signalCursorActivity(cm); + } + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function (line) { + var len = lineLength(line); + + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + + if (recomputeMaxLength) { + cm.curOp.updateMaxLine = true; + } + } + + retreatFrontier(doc, from.line); + startWorker(cm, 400); + var lendiff = change.text.length - (to.line - from.line) - 1; // Remember that these lines changed, for updating the display + + if (change.full) { + regChange(cm); + } else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) { + regLineChange(cm, from.line, "text"); + } else { + regChange(cm, from.line, to.line + 1, lendiff); + } + + var changesHandler = hasHandler(cm, "changes"), + changeHandler = hasHandler(cm, "change"); + + if (changeHandler || changesHandler) { + var obj = { + from: from, + to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + + if (changeHandler) { + signalLater(cm, "change", cm, obj); + } + + if (changesHandler) { + (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); + } + } + + cm.display.selForContextMenu = null; + } + + function _replaceRange(doc, code, from, to, origin) { + var assign; + + if (!to) { + to = from; + } + + if (cmp(to, from) < 0) { + assign = [to, from], from = assign[0], to = assign[1]; + } + + if (typeof code == "string") { + code = doc.splitLines(code); + } + + makeChange(doc, { + from: from, + to: to, + text: code, + origin: origin + }); + } // Rebasing/resetting history to deal with externally-sourced changes + + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + + + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], + ok = true; + + if (sub.ranges) { + if (!sub.copied) { + sub = array[i] = sub.deepCopy(); + sub.copied = true; + } + + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + + continue; + } + + for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { + var cur = sub.changes[j$1]; + + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break; + } + } + + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, + to = change.to.line, + diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + + + function changeLine(doc, handle, changeType, op) { + var no = handle, + line = handle; + + if (typeof handle == "number") { + line = getLine(doc, clipLine(doc, handle)); + } else { + no = lineNo(handle); + } + + if (no == null) { + return null; + } + + if (op(line, no) && doc.cm) { + regLineChange(doc.cm, no, changeType); + } + + return line; + } // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + + function LeafChunk(lines) { + var this$1 = this; + this.lines = lines; + this.parent = null; + var height = 0; + + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this$1; + height += lines[i].height; + } + + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function chunkSize() { + return this.lines.length; + }, + // Remove the n lines at offset 'at'. + removeInner: function removeInner(at, n) { + var this$1 = this; + + for (var i = at, e = at + n; i < e; ++i) { + var line = this$1.lines[i]; + this$1.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + + this.lines.splice(at, n); + }, + // Helper used to collapse a small branch into a single leaf. + collapse: function collapse(lines) { + lines.push.apply(lines, this.lines); + }, + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function insertInner(at, lines, height) { + var this$1 = this; + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this$1; + } + }, + // Used to iterate over a part of the tree. + iterN: function iterN(at, n, op) { + var this$1 = this; + + for (var e = at + n; at < e; ++at) { + if (op(this$1.lines[at])) { + return true; + } + } + } + }; + + function BranchChunk(children) { + var this$1 = this; + this.children = children; + var size = 0, + height = 0; + + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); + height += ch.height; + ch.parent = this$1; + } + + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function chunkSize() { + return this.size; + }, + removeInner: function removeInner(at, n) { + var this$1 = this; + this.size -= n; + + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], + sz = child.chunkSize(); + + if (at < sz) { + var rm = Math.min(n, sz - at), + oldHeight = child.height; + child.removeInner(at, rm); + this$1.height -= oldHeight - child.height; + + if (sz == rm) { + this$1.children.splice(i--, 1); + child.parent = null; + } + + if ((n -= rm) == 0) { + break; + } + + at = 0; + } else { + at -= sz; + } + } // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + + + if (this.size - n < 25 && (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function collapse(lines) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { + this$1.children[i].collapse(lines); + } + }, + insertInner: function insertInner(at, lines, height) { + var this$1 = this; + this.size += lines.length; + this.height += height; + + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], + sz = child.chunkSize(); + + if (at <= sz) { + child.insertInner(at, lines, height); + + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25; + + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this$1.children.splice(++i, 0, leaf); + leaf.parent = this$1; + } + + child.lines = child.lines.slice(0, remaining); + this$1.maybeSpill(); + } + + break; + } + + at -= sz; + } + }, + // When a node has grown, check whether it should be split. + maybeSpill: function maybeSpill() { + if (this.children.length <= 10) { + return; + } + + var me = this; + + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + + if (!me.parent) { + // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + + sibling.parent = me.parent; + } while (me.children.length > 10); + + me.parent.maybeSpill(); + }, + iterN: function iterN(at, n, op) { + var this$1 = this; + + for (var i = 0; i < this.children.length; ++i) { + var child = this$1.children[i], + sz = child.chunkSize(); + + if (at < sz) { + var used = Math.min(n, sz - at); + + if (child.iterN(at, used, op)) { + return true; + } + + if ((n -= used) == 0) { + break; + } + + at = 0; + } else { + at -= sz; + } + } + } + }; // Line widgets are block elements displayed above or below a line. + + var LineWidget = function LineWidget(doc, node, options) { + var this$1 = this; + + if (options) { + for (var opt in options) { + if (options.hasOwnProperty(opt)) { + this$1[opt] = options[opt]; + } + } + } + + this.doc = doc; + this.node = node; + }; + + LineWidget.prototype.clear = function () { + var this$1 = this; + var cm = this.doc.cm, + ws = this.line.widgets, + line = this.line, + no = lineNo(line); + + if (no == null || !ws) { + return; + } + + for (var i = 0; i < ws.length; ++i) { + if (ws[i] == this$1) { + ws.splice(i--, 1); + } + } + + if (!ws.length) { + line.widgets = null; + } + + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + + if (cm) { + runInOp(cm, function () { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + signalLater(cm, "lineWidgetCleared", cm, this, no); + } + }; + + LineWidget.prototype.changed = function () { + var this$1 = this; + var oldH = this.height, + cm = this.doc.cm, + line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + + if (!diff) { + return; + } + + if (!lineIsHidden(this.doc, line)) { + updateLineHeight(line, line.height + diff); + } + + if (cm) { + runInOp(cm, function () { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); + }); + } + }; + + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (_heightAtLine(line) < (cm.curOp && cm.curOp.scrollTop || cm.doc.scrollTop)) { + addToScrollTop(cm, diff); + } + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + + if (cm && widget.noHScroll) { + cm.display.alignWidgets = true; + } + + changeLine(doc, handle, "widget", function (line) { + var widgets = line.widgets || (line.widgets = []); + + if (widget.insertAt == null) { + widgets.push(widget); + } else { + widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); + } + + widget.line = line; + + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = _heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + + if (aboveVisible) { + addToScrollTop(cm, widget.height); + } + + cm.curOp.forceUpdate = true; + } + + return true; + }); + + if (cm) { + signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); + } + + return widget; + } // TEXTMARKERS + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + + + var nextMarkerId = 0; + + var TextMarker = function TextMarker(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; // Clear the marker. + + + TextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { + return; + } + + var cm = this.doc.cm, + withOp = cm && !cm.curOp; + + if (withOp) { + _startOperation(cm); + } + + if (hasHandler(this, "clear")) { + var found = this.find(); + + if (found) { + signalLater(this, "clear", found.from, found.to); + } + } + + var min = null, + max = null; + + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this$1); + + if (cm && !this$1.collapsed) { + regLineChange(cm, lineNo(line), "text"); + } else if (cm) { + if (span.to != null) { + max = lineNo(line); + } + + if (span.from != null) { + min = lineNo(line); + } + } + + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + + if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) { + updateLineHeight(line, textHeight(cm.display)); + } + } + + if (cm && this.collapsed && !cm.options.lineWrapping) { + for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { + var visual = visualLine(this$1.lines[i$1]), + len = lineLength(visual); + + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } + } + + if (min != null && cm && this.collapsed) { + regChange(cm, min, max + 1); + } + + this.lines.length = 0; + this.explicitlyCleared = true; + + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + + if (cm) { + reCheckSelection(cm.doc); + } + } + + if (cm) { + signalLater(cm, "markerCleared", cm, this, min, max); + } + + if (withOp) { + _endOperation(cm); + } + + if (this.parent) { + this.parent.clear(); + } + }; // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + + + TextMarker.prototype.find = function (side, lineObj) { + var this$1 = this; + + if (side == null && this.type == "bookmark") { + side = 1; + } + + var from, to; + + for (var i = 0; i < this.lines.length; ++i) { + var line = this$1.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this$1); + + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + + if (side == -1) { + return from; + } + } + + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + + if (side == 1) { + return to; + } + } + } + + return from && { + from: from, + to: to + }; + }; // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + + + TextMarker.prototype.changed = function () { + var this$1 = this; + var pos = this.find(-1, true), + widget = this, + cm = this.doc.cm; + + if (!pos || !cm) { + return; + } + + runInOp(cm, function () { + var line = pos.line, + lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + + cm.curOp.updateMaxLine = true; + + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + + if (dHeight) { + updateLineHeight(line, line.height + dHeight); + } + } + + signalLater(cm, "markerChanged", cm, this$1); + }); + }; + + TextMarker.prototype.attachLine = function (line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) { + (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); + } + } + + this.lines.push(line); + }; + + TextMarker.prototype.detachLine = function (line) { + this.lines.splice(indexOf(this.lines, line), 1); + + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + + eventMixin(TextMarker); // Create a marker, wire it up to the right lines, and + + function _markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) { + return markTextShared(doc, from, to, options, type); + } // Ensure we are in an operation. + + + if (doc.cm && !doc.cm.curOp) { + return operation(doc.cm, _markText)(doc, from, to, options, type); + } + + var marker = new TextMarker(doc, type), + diff = cmp(from, to); + + if (options) { + copyObj(options, marker, false); + } // Don't connect empty markers unless clearWhenEmpty is false + + + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) { + return marker; + } + + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); + + if (!options.handleMouseEvents) { + marker.widgetNode.setAttribute("cm-ignore-events", "true"); + } + + if (options.insertLeft) { + marker.widgetNode.insertLeft = true; + } + } + + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) { + throw new Error("Inserting collapsed marker partially overlapping an existing one"); + } + + seeCollapsedSpans(); + } + + if (marker.addToHistory) { + addChangeToHistory(doc, { + from: from, + to: to, + origin: "markText" + }, doc.sel, NaN); + } + + var curLine = from.line, + cm = doc.cm, + updateMaxLine; + doc.iter(curLine, to.line + 1, function (line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) { + updateMaxLine = true; + } + + if (marker.collapsed && curLine != from.line) { + updateLineHeight(line, 0); + } + + addMarkedSpan(line, new MarkedSpan(marker, curLine == from.line ? from.ch : null, curLine == to.line ? to.ch : null)); + ++curLine; + }); // lineIsHidden depends on the presence of the spans, so needs a second pass + + if (marker.collapsed) { + doc.iter(from.line, to.line + 1, function (line) { + if (lineIsHidden(doc, line)) { + updateLineHeight(line, 0); + } + }); + } + + if (marker.clearOnEnter) { + on(marker, "beforeCursorEnter", function () { + return marker.clear(); + }); + } + + if (marker.readOnly) { + seeReadOnlySpans(); + + if (doc.history.done.length || doc.history.undone.length) { + doc.clearHistory(); + } + } + + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + + if (cm) { + // Sync editor state + if (updateMaxLine) { + cm.curOp.updateMaxLine = true; + } + + if (marker.collapsed) { + regChange(cm, from.line, to.line + 1); + } else if (marker.className || marker.startStyle || marker.endStyle || marker.css || marker.attributes || marker.title) { + for (var i = from.line; i <= to.line; i++) { + regLineChange(cm, i, "text"); + } + } + + if (marker.atomic) { + reCheckSelection(cm.doc); + } + + signalLater(cm, "markerAdded", cm, marker); + } + + return marker; + } // SHARED TEXTMARKERS + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + + + var SharedTextMarker = function SharedTextMarker(markers, primary) { + var this$1 = this; + this.markers = markers; + this.primary = primary; + + for (var i = 0; i < markers.length; ++i) { + markers[i].parent = this$1; + } + }; + + SharedTextMarker.prototype.clear = function () { + var this$1 = this; + + if (this.explicitlyCleared) { + return; + } + + this.explicitlyCleared = true; + + for (var i = 0; i < this.markers.length; ++i) { + this$1.markers[i].clear(); + } + + signalLater(this, "clear"); + }; + + SharedTextMarker.prototype.find = function (side, lineObj) { + return this.primary.find(side, lineObj); + }; + + eventMixin(SharedTextMarker); + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [_markText(doc, from, to, options, type)], + primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function (doc) { + if (widget) { + options.widgetNode = widget.cloneNode(true); + } + + markers.push(_markText(doc, _clipPos(doc, from), _clipPos(doc, to), options, type)); + + for (var i = 0; i < doc.linked.length; ++i) { + if (doc.linked[i].isParent) { + return; + } + } + + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary); + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { + return m.parent; + }); + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], + pos = marker.find(); + var mFrom = doc.clipPos(pos.from), + mTo = doc.clipPos(pos.to); + + if (cmp(mFrom, mTo)) { + var subMark = _markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + var loop = function loop(i) { + var marker = markers[i], + linked = [marker.primary.doc]; + linkedDocs(marker.primary.doc, function (d) { + return linked.push(d); + }); + + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + }; + + for (var i = 0; i < markers.length; i++) { + loop(i); + } + } + + var nextDocId = 0; + + var Doc = function Doc(text, mode, firstLine, lineSep, direction) { + if (!(this instanceof Doc)) { + return new Doc(text, mode, firstLine, lineSep, direction); + } + + if (firstLine == null) { + firstLine = 0; + } + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.modeFrontier = this.highlightFrontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.direction = direction == "rtl" ? "rtl" : "ltr"; + this.extend = false; + + if (typeof text == "string") { + text = this.splitLines(text); + } + + updateDoc(this, { + from: start, + to: start, + text: text + }); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function iter(from, to, op) { + if (op) { + this.iterN(from - this.first, to - from, op); + } else { + this.iterN(this.first, this.first + this.size, from); + } + }, + // Non-public interface for adding and removing lines. + insert: function insert(at, lines) { + var height = 0; + + for (var i = 0; i < lines.length; ++i) { + height += lines[i].height; + } + + this.insertInner(at - this.first, lines, height); + }, + remove: function remove(at, n) { + this.removeInner(at - this.first, n); + }, + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + getValue: function getValue(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + + if (lineSep === false) { + return lines; + } + + return lines.join(lineSep || this.lineSeparator()); + }, + setValue: docMethodOp(function (code) { + var top = Pos(this.first, 0), + last = this.first + this.size - 1; + makeChange(this, { + from: top, + to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), + origin: "setValue", + full: true + }, true); + + if (this.cm) { + scrollToCoords(this.cm, 0, 0); + } + + setSelection(this, simpleSelection(top), sel_dontScroll); + }), + replaceRange: function replaceRange(code, from, to, origin) { + from = _clipPos(this, from); + to = to ? _clipPos(this, to) : from; + + _replaceRange(this, code, from, to, origin); + }, + getRange: function getRange(from, to, lineSep) { + var lines = getBetween(this, _clipPos(this, from), _clipPos(this, to)); + + if (lineSep === false) { + return lines; + } + + return lines.join(lineSep || this.lineSeparator()); + }, + getLine: function getLine(line) { + var l = this.getLineHandle(line); + return l && l.text; + }, + getLineHandle: function getLineHandle(line) { + if (isLine(this, line)) { + return getLine(this, line); + } + }, + getLineNumber: function getLineNumber(line) { + return lineNo(line); + }, + getLineHandleVisualStart: function getLineHandleVisualStart(line) { + if (typeof line == "number") { + line = getLine(this, line); + } + + return visualLine(line); + }, + lineCount: function lineCount() { + return this.size; + }, + firstLine: function firstLine() { + return this.first; + }, + lastLine: function lastLine() { + return this.first + this.size - 1; + }, + clipPos: function clipPos(pos) { + return _clipPos(this, pos); + }, + getCursor: function getCursor(start) { + var range$$1 = this.sel.primary(), + pos; + + if (start == null || start == "head") { + pos = range$$1.head; + } else if (start == "anchor") { + pos = range$$1.anchor; + } else if (start == "end" || start == "to" || start === false) { + pos = range$$1.to(); + } else { + pos = range$$1.from(); + } + + return pos; + }, + listSelections: function listSelections() { + return this.sel.ranges; + }, + somethingSelected: function somethingSelected() { + return this.sel.somethingSelected(); + }, + setCursor: docMethodOp(function (line, ch, options) { + setSimpleSelection(this, _clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function (anchor, head, options) { + setSimpleSelection(this, _clipPos(this, anchor), _clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function (head, other, options) { + extendSelection(this, _clipPos(this, head), other && _clipPos(this, other), options); + }), + extendSelections: docMethodOp(function (heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function (f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function (ranges, primary, options) { + var this$1 = this; + + if (!ranges.length) { + return; + } + + var out = []; + + for (var i = 0; i < ranges.length; i++) { + out[i] = new Range(_clipPos(this$1, ranges[i].anchor), _clipPos(this$1, ranges[i].head)); + } + + if (primary == null) { + primary = Math.min(ranges.length - 1, this.sel.primIndex); + } + + setSelection(this, normalizeSelection(this.cm, out, primary), options); + }), + addSelection: docMethodOp(function (anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(_clipPos(this, anchor), _clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); + }), + getSelection: function getSelection(lineSep) { + var this$1 = this; + var ranges = this.sel.ranges, + lines; + + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + + if (lineSep === false) { + return lines; + } else { + return lines.join(lineSep || this.lineSeparator()); + } + }, + getSelections: function getSelections(lineSep) { + var this$1 = this; + var parts = [], + ranges = this.sel.ranges; + + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); + + if (lineSep !== false) { + sel = sel.join(lineSep || this$1.lineSeparator()); + } + + parts[i] = sel; + } + + return parts; + }, + replaceSelection: function replaceSelection(code, collapse, origin) { + var dup = []; + + for (var i = 0; i < this.sel.ranges.length; i++) { + dup[i] = code; + } + + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function (code, collapse, origin) { + var this$1 = this; + var changes = [], + sel = this.sel; + + for (var i = 0; i < sel.ranges.length; i++) { + var range$$1 = sel.ranges[i]; + changes[i] = { + from: range$$1.from(), + to: range$$1.to(), + text: this$1.splitLines(code[i]), + origin: origin + }; + } + + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + + for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) { + makeChange(this$1, changes[i$1]); + } + + if (newSel) { + setSelectionReplaceHistory(this, newSel); + } else if (this.cm) { + ensureCursorVisible(this.cm); + } + }), + undo: docMethodOp(function () { + makeChangeFromHistory(this, "undo"); + }), + redo: docMethodOp(function () { + makeChangeFromHistory(this, "redo"); + }), + undoSelection: docMethodOp(function () { + makeChangeFromHistory(this, "undo", true); + }), + redoSelection: docMethodOp(function () { + makeChangeFromHistory(this, "redo", true); + }), + setExtending: function setExtending(val) { + this.extend = val; + }, + getExtending: function getExtending() { + return this.extend; + }, + historySize: function historySize() { + var hist = this.history, + done = 0, + undone = 0; + + for (var i = 0; i < hist.done.length; i++) { + if (!hist.done[i].ranges) { + ++done; + } + } + + for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { + if (!hist.undone[i$1].ranges) { + ++undone; + } + } + + return { + undo: done, + redo: undone + }; + }, + clearHistory: function clearHistory() { + this.history = new History(this.history.maxGeneration); + }, + markClean: function markClean() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function changeGeneration(forceSplit) { + if (forceSplit) { + this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; + } + + return this.history.generation; + }, + isClean: function isClean(gen) { + return this.history.generation == (gen || this.cleanGeneration); + }, + getHistory: function getHistory() { + return { + done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone) + }; + }, + setHistory: function setHistory(histData) { + var hist = this.history = new History(this.history.maxGeneration); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + setGutterMarker: docMethodOp(function (line, gutterID, value) { + return changeLine(this, line, "gutter", function (line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + + if (!value && isEmpty(markers)) { + line.gutterMarkers = null; + } + + return true; + }); + }), + clearGutter: docMethodOp(function (gutterID) { + var this$1 = this; + this.iter(function (line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + changeLine(this$1, line, "gutter", function () { + line.gutterMarkers[gutterID] = null; + + if (isEmpty(line.gutterMarkers)) { + line.gutterMarkers = null; + } + + return true; + }); + } + }); + }), + lineInfo: function lineInfo(line) { + var n; + + if (typeof line == "number") { + if (!isLine(this, line)) { + return null; + } + + n = line; + line = getLine(this, line); + + if (!line) { + return null; + } + } else { + n = lineNo(line); + + if (n == null) { + return null; + } + } + + return { + line: n, + handle: line, + text: line.text, + gutterMarkers: line.gutterMarkers, + textClass: line.textClass, + bgClass: line.bgClass, + wrapClass: line.wrapClass, + widgets: line.widgets + }; + }, + addLineClass: docMethodOp(function (handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; + + if (!line[prop]) { + line[prop] = cls; + } else if (classTest(cls).test(line[prop])) { + return false; + } else { + line[prop] += " " + cls; + } + + return true; + }); + }), + removeLineClass: docMethodOp(function (handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + + if (!cur) { + return false; + } else if (cls == null) { + line[prop] = null; + } else { + var found = cur.match(classTest(cls)); + + if (!found) { + return false; + } + + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + + return true; + }); + }), + addLineWidget: docMethodOp(function (handle, node, options) { + return addLineWidget(this, handle, node, options); + }), + removeLineWidget: function removeLineWidget(widget) { + widget.clear(); + }, + markText: function markText(from, to, options) { + return _markText(this, _clipPos(this, from), _clipPos(this, to), options, options && options.type || "range"); + }, + setBookmark: function setBookmark(pos, options) { + var realOpts = { + replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, + shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents + }; + pos = _clipPos(this, pos); + return _markText(this, pos, pos, realOpts, "bookmark"); + }, + findMarksAt: function findMarksAt(pos) { + pos = _clipPos(this, pos); + var markers = [], + spans = getLine(this, pos.line).markedSpans; + + if (spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + + if ((span.from == null || span.from <= pos.ch) && (span.to == null || span.to >= pos.ch)) { + markers.push(span.marker.parent || span.marker); + } + } + } + + return markers; + }, + findMarks: function findMarks(from, to, filter) { + from = _clipPos(this, from); + to = _clipPos(this, to); + var found = [], + lineNo$$1 = from.line; + this.iter(from.line, to.line + 1, function (line) { + var spans = line.markedSpans; + + if (spans) { + for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + + if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to || span.from == null && lineNo$$1 != from.line || span.from != null && lineNo$$1 == to.line && span.from >= to.ch) && (!filter || filter(span.marker))) { + found.push(span.marker.parent || span.marker); + } + } + } + + ++lineNo$$1; + }); + return found; + }, + getAllMarks: function getAllMarks() { + var markers = []; + this.iter(function (line) { + var sps = line.markedSpans; + + if (sps) { + for (var i = 0; i < sps.length; ++i) { + if (sps[i].from != null) { + markers.push(sps[i].marker); + } + } + } + }); + return markers; + }, + posFromIndex: function posFromIndex(off) { + var ch, + lineNo$$1 = this.first, + sepSize = this.lineSeparator().length; + this.iter(function (line) { + var sz = line.text.length + sepSize; + + if (sz > off) { + ch = off; + return true; + } + + off -= sz; + ++lineNo$$1; + }); + return _clipPos(this, Pos(lineNo$$1, ch)); + }, + indexFromPos: function indexFromPos(coords) { + coords = _clipPos(this, coords); + var index = coords.ch; + + if (coords.line < this.first || coords.ch < 0) { + return 0; + } + + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { + // iter aborts when callback returns a truthy value + index += line.text.length + sepSize; + }); + return index; + }, + copy: function copy(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first, this.lineSep, this.direction); + doc.scrollTop = this.scrollTop; + doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + + return doc; + }, + linkedDoc: function linkedDoc(options) { + if (!options) { + options = {}; + } + + var from = this.first, + to = this.first + this.size; + + if (options.from != null && options.from > from) { + from = options.from; + } + + if (options.to != null && options.to < to) { + to = options.to; + } + + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); + + if (options.sharedHist) { + copy.history = this.history; + } + + (this.linked || (this.linked = [])).push({ + doc: copy, + sharedHist: options.sharedHist + }); + copy.linked = [{ + doc: this, + isParent: true, + sharedHist: options.sharedHist + }]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy; + }, + unlinkDoc: function unlinkDoc(other) { + var this$1 = this; + + if (other instanceof CodeMirror) { + other = other.doc; + } + + if (this.linked) { + for (var i = 0; i < this.linked.length; ++i) { + var link = this$1.linked[i]; + + if (link.doc != other) { + continue; + } + + this$1.linked.splice(i, 1); + other.unlinkDoc(this$1); + detachSharedMarkers(findSharedMarkers(this$1)); + break; + } + } // If the histories were shared, split them again + + + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function (doc) { + return splitIds.push(doc.id); + }, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function iterLinkedDocs(f) { + linkedDocs(this, f); + }, + getMode: function getMode() { + return this.mode; + }, + getEditor: function getEditor() { + return this.cm; + }, + splitLines: function splitLines(str) { + if (this.lineSep) { + return str.split(this.lineSep); + } + + return splitLinesAuto(str); + }, + lineSeparator: function lineSeparator() { + return this.lineSep || "\n"; + }, + setDirection: docMethodOp(function (dir) { + if (dir != "rtl") { + dir = "ltr"; + } + + if (dir == this.direction) { + return; + } + + this.direction = dir; + this.iter(function (line) { + return line.order = null; + }); + + if (this.cm) { + directionChanged(this.cm); + } + }) + }); // Public alias. + + Doc.prototype.eachLine = Doc.prototype.iter; // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { + return; + } + + e_preventDefault(e); + + if (ie) { + lastDrop = +new Date(); + } + + var pos = posFromMouse(cm, e, true), + files = e.dataTransfer.files; + + if (!pos || cm.isReadOnly()) { + return; + } // Might be a file drop, in which case we simply extract the text + // and insert it. + + + if (files && files.length && window.FileReader && window.File) { + var n = files.length, + text = Array(n), + read = 0; + + var loadFile = function loadFile(file, i) { + if (cm.options.allowDropFileTypes && indexOf(cm.options.allowDropFileTypes, file.type) == -1) { + return; + } + + var reader = new FileReader(); + reader.onload = operation(cm, function () { + var content = reader.result; + + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { + content = ""; + } + + text[i] = content; + + if (++read == n) { + pos = _clipPos(cm.doc, pos); + var change = { + from: pos, + to: pos, + text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + origin: "paste" + }; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); + } + }); + reader.readAsText(file); + }; + + for (var i = 0; i < n; ++i) { + loadFile(files[i], i); + } + } else { + // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); // Ensure the editor is re-focused + + setTimeout(function () { + return cm.display.input.focus(); + }, 20); + return; + } + + try { + var text$1 = e.dataTransfer.getData("Text"); + + if (text$1) { + var selected; + + if (cm.state.draggingText && !cm.state.draggingText.copy) { + selected = cm.listSelections(); + } + + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + + if (selected) { + for (var i$1 = 0; i$1 < selected.length; ++i$1) { + _replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); + } + } + + cm.replaceSelection(text$1, "around", "paste"); + cm.display.input.focus(); + } + } catch (e) {} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date() - lastDrop < 100)) { + e_stop(e); + return; + } + + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { + return; + } + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove"; // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); // Force a relayout, or Opera won't use our image for some obscure reason + + img._top = img.offsetTop; + } + + e.dataTransfer.setDragImage(img, 0, 0); + + if (presto) { + img.parentNode.removeChild(img); + } + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + + if (!pos) { + return; + } + + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + + function forEachCodeMirror(f) { + if (!document.getElementsByClassName) { + return; + } + + var byClass = document.getElementsByClassName("CodeMirror"), + editors = []; + + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + + if (cm) { + editors.push(cm); + } + } + + if (editors.length) { + editors[0].operation(function () { + for (var i = 0; i < editors.length; i++) { + f(editors[i]); + } + }); + } + } + + var globalsRegistered = false; + + function ensureGlobalHandlers() { + if (globalsRegistered) { + return; + } + + registerGlobalHandlers(); + globalsRegistered = true; + } + + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function () { + if (resizeTimer == null) { + resizeTimer = setTimeout(function () { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); + } + }); // When the window loses focus, we want to show the editor as blurred + + on(window, "blur", function () { + return forEachCodeMirror(onBlur); + }); + } // Called when the window resizes + + + function onResize(cm) { + var d = cm.display; // Might be a text scaling operation, clear size caches. + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + var keyNames = { + 3: "Pause", + 8: "Backspace", + 9: "Tab", + 13: "Enter", + 16: "Shift", + 17: "Ctrl", + 18: "Alt", + 19: "Pause", + 20: "CapsLock", + 27: "Esc", + 32: "Space", + 33: "PageUp", + 34: "PageDown", + 35: "End", + 36: "Home", + 37: "Left", + 38: "Up", + 39: "Right", + 40: "Down", + 44: "PrintScrn", + 45: "Insert", + 46: "Delete", + 59: ";", + 61: "=", + 91: "Mod", + 92: "Mod", + 93: "Mod", + 106: "*", + 107: "=", + 109: "-", + 110: ".", + 111: "/", + 145: "ScrollLock", + 173: "-", + 186: ";", + 187: "=", + 188: ",", + 189: "-", + 190: ".", + 191: "/", + 192: "`", + 219: "[", + 220: "\\", + 221: "]", + 222: "'", + 63232: "Up", + 63233: "Down", + 63234: "Left", + 63235: "Right", + 63272: "Delete", + 63273: "Home", + 63275: "End", + 63276: "PageUp", + 63277: "PageDown", + 63302: "Insert" + }; // Number keys + + for (var i = 0; i < 10; i++) { + keyNames[i + 48] = keyNames[i + 96] = String(i); + } // Alphabetic keys + + + for (var i$1 = 65; i$1 <= 90; i$1++) { + keyNames[i$1] = String.fromCharCode(i$1); + } // Function keys + + + for (var i$2 = 1; i$2 <= 12; i$2++) { + keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; + } + + var keyMap = {}; + keyMap.basic = { + "Left": "goCharLeft", + "Right": "goCharRight", + "Up": "goLineUp", + "Down": "goLineDown", + "End": "goLineEnd", + "Home": "goLineStartSmart", + "PageUp": "goPageUp", + "PageDown": "goPageDown", + "Delete": "delCharAfter", + "Backspace": "delCharBefore", + "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", + "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", + "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + + keyMap.pcDefault = { + "Ctrl-A": "selectAll", + "Ctrl-D": "deleteLine", + "Ctrl-Z": "undo", + "Shift-Ctrl-Z": "redo", + "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", + "Ctrl-End": "goDocEnd", + "Ctrl-Up": "goLineUp", + "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", + "Ctrl-Right": "goGroupRight", + "Alt-Left": "goLineStart", + "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", + "Ctrl-Delete": "delGroupAfter", + "Ctrl-S": "save", + "Ctrl-F": "find", + "Ctrl-G": "findNext", + "Shift-Ctrl-G": "findPrev", + "Shift-Ctrl-F": "replace", + "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", + "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", + "Shift-Ctrl-U": "redoSelection", + "Alt-U": "redoSelection", + "fallthrough": "basic" + }; // Very basic readline/emacs-style bindings, which are standard on Mac. + + keyMap.emacsy = { + "Ctrl-F": "goCharRight", + "Ctrl-B": "goCharLeft", + "Ctrl-P": "goLineUp", + "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", + "Alt-B": "goWordLeft", + "Ctrl-A": "goLineStart", + "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", + "Shift-Ctrl-V": "goPageUp", + "Ctrl-D": "delCharAfter", + "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", + "Alt-Backspace": "delWordBefore", + "Ctrl-K": "killLine", + "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", + "Cmd-D": "deleteLine", + "Cmd-Z": "undo", + "Shift-Cmd-Z": "redo", + "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", + "Cmd-Up": "goDocStart", + "Cmd-End": "goDocEnd", + "Cmd-Down": "goDocEnd", + "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", + "Cmd-Left": "goLineLeft", + "Cmd-Right": "goLineRight", + "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", + "Alt-Delete": "delGroupAfter", + "Cmd-S": "save", + "Cmd-F": "find", + "Cmd-G": "findNext", + "Shift-Cmd-G": "findPrev", + "Cmd-Alt-F": "replace", + "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", + "Cmd-]": "indentMore", + "Cmd-Backspace": "delWrappedLineLeft", + "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", + "Shift-Cmd-U": "redoSelection", + "Ctrl-Up": "goDocStart", + "Ctrl-Down": "goDocEnd", + "fallthrough": ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/); + name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + + if (/^(cmd|meta|m)$/i.test(mod)) { + cmd = true; + } else if (/^a(lt)?$/i.test(mod)) { + alt = true; + } else if (/^(c|ctrl|control)$/i.test(mod)) { + ctrl = true; + } else if (/^s(hift)?$/i.test(mod)) { + shift = true; + } else { + throw new Error("Unrecognized modifier name: " + mod); + } + } + + if (alt) { + name = "Alt-" + name; + } + + if (ctrl) { + name = "Ctrl-" + name; + } + + if (cmd) { + name = "Cmd-" + name; + } + + if (shift) { + name = "Shift-" + name; + } + + return name; + } // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + + + function normalizeKeyMap(keymap) { + var copy = {}; + + for (var keyname in keymap) { + if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { + continue; + } + + if (value == "...") { + delete keymap[keyname]; + continue; + } + + var keys = map(keyname.split(" "), normalizeKeyName); + + for (var i = 0; i < keys.length; i++) { + var val = void 0, + name = void 0; + + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + + var prev = copy[name]; + + if (!prev) { + copy[name] = val; + } else if (prev != val) { + throw new Error("Inconsistent bindings for " + name); + } + } + + delete keymap[keyname]; + } + } + + for (var prop in copy) { + keymap[prop] = copy[prop]; + } + + return keymap; + } + + function lookupKey(key, map$$1, handle, context) { + map$$1 = getKeyMap(map$$1); + var found = map$$1.call ? map$$1.call(key, context) : map$$1[key]; + + if (found === false) { + return "nothing"; + } + + if (found === "...") { + return "multi"; + } + + if (found != null && handle(found)) { + return "handled"; + } + + if (map$$1.fallthrough) { + if (Object.prototype.toString.call(map$$1.fallthrough) != "[object Array]") { + return lookupKey(key, map$$1.fallthrough, handle, context); + } + + for (var i = 0; i < map$$1.fallthrough.length; i++) { + var result = lookupKey(key, map$$1.fallthrough[i], handle, context); + + if (result) { + return result; + } + } + } + } // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + + + function isModifierKey(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + } + + function addModifierNames(name, event, noShift) { + var base = name; + + if (event.altKey && base != "Alt") { + name = "Alt-" + name; + } + + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { + name = "Ctrl-" + name; + } + + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { + name = "Cmd-" + name; + } + + if (!noShift && event.shiftKey && base != "Shift") { + name = "Shift-" + name; + } + + return name; + } // Look up the name of a key as indicated by an event object. + + + function keyName(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) { + return false; + } + + var name = keyNames[event.keyCode]; + + if (name == null || event.altGraphKey) { + return false; + } // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, + // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) + + + if (event.keyCode == 3 && event.code) { + name = event.code; + } + + return addModifierNames(name, event, noShift); + } + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val; + } // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + + + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, + kill = []; // Build up a set of ranges to kill first, merging overlapping + // ranges. + + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break; + } + } + + kill.push(toKill); + } // Next, remove those actual ranges. + + + runInOp(cm, function () { + for (var i = kill.length - 1; i >= 0; i--) { + _replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); + } + + ensureCursorVisible(cm); + }); + } + + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir); + return target < 0 || target > line.text.length ? null : target; + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir); + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before"); + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + var order = getOrder(lineObj, cm.doc.direction); + + if (order) { + var part = dir < 0 ? lst(order) : order[0]; + var moveInStorageOrder = dir < 0 == (part.level == 1); + var sticky = moveInStorageOrder ? "after" : "before"; + var ch; // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + + if (part.level > 0 || cm.doc.direction == "rtl") { + var prep = prepareMeasureForLine(cm, lineObj); + ch = dir < 0 ? lineObj.text.length - 1 : 0; + var targetTop = measureCharPrepared(cm, prep, ch).top; + ch = findFirst(function (ch) { + return measureCharPrepared(cm, prep, ch).top == targetTop; + }, dir < 0 == (part.level == 1) ? part.from : part.to - 1, ch); + + if (sticky == "before") { + ch = moveCharLogically(lineObj, ch, 1); + } + } else { + ch = dir < 0 ? part.to : part.from; + } + + return new Pos(lineNo, ch, sticky); + } + } + + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after"); + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction); + + if (!bidi) { + return moveLogically(line, start, dir); + } + + if (start.ch >= line.text.length) { + start.ch = line.text.length; + start.sticky = "before"; + } else if (start.ch <= 0) { + start.ch = 0; + start.sticky = "after"; + } + + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), + part = bidi[partPos]; + + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir); + } + + var mv = function mv(pos, dir) { + return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); + }; + + var prep; + + var getWrappedLineExtent = function getWrappedLineExtent(ch) { + if (!cm.options.lineWrapping) { + return { + begin: 0, + end: line.text.length + }; + } + + prep = prep || prepareMeasureForLine(cm, line); + return wrappedLineExtentChar(cm, line, prep, ch); + }; + + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = part.level == 1 == dir < 0; + var ch = mv(start, moveInStorageOrder ? 1 : -1); + + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after"; + return new Pos(start.line, ch, sticky); + } + } // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + + var searchInVisualLine = function searchInVisualLine(partPos, dir, wrappedLineExtent) { + var getRes = function getRes(ch, moveInStorageOrder) { + return moveInStorageOrder ? new Pos(start.line, mv(ch, 1), "before") : new Pos(start.line, ch, "after"); + }; + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos]; + var moveInStorageOrder = dir > 0 == (part.level != 1); + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); + + if (part.from <= ch && ch < part.to) { + return getRes(ch, moveInStorageOrder); + } + + ch = moveInStorageOrder ? part.from : mv(part.to, -1); + + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { + return getRes(ch, moveInStorageOrder); + } + } + }; // Case 3a: Look for other bidi parts on the same visual line + + + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); + + if (res) { + return res; + } // Case 3b: Look for other bidi parts on the next visual line + + + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); + + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); + + if (res) { + return res; + } + } // Case 4: Nowhere to move + + + return null; + } // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + + + var commands = { + selectAll: selectAll, + singleSelection: function singleSelection(cm) { + return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); + }, + killLine: function killLine(cm) { + return deleteNearSelection(cm, function (range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + + if (range.head.ch == len && range.head.line < cm.lastLine()) { + return { + from: range.head, + to: Pos(range.head.line + 1, 0) + }; + } else { + return { + from: range.head, + to: Pos(range.head.line, len) + }; + } + } else { + return { + from: range.from(), + to: range.to() + }; + } + }); + }, + deleteLine: function deleteLine(cm) { + return deleteNearSelection(cm, function (range) { + return { + from: Pos(range.from().line, 0), + to: _clipPos(cm.doc, Pos(range.to().line + 1, 0)) + }; + }); + }, + delLineLeft: function delLineLeft(cm) { + return deleteNearSelection(cm, function (range) { + return { + from: Pos(range.from().line, 0), + to: range.from() + }; + }); + }, + delWrappedLineLeft: function delWrappedLineLeft(cm) { + return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({ + left: 0, + top: top + }, "div"); + return { + from: leftPos, + to: range.from() + }; + }); + }, + delWrappedLineRight: function delWrappedLineRight(cm) { + return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({ + left: cm.display.lineDiv.offsetWidth + 100, + top: top + }, "div"); + return { + from: range.from(), + to: rightPos + }; + }); + }, + undo: function undo(cm) { + return cm.undo(); + }, + redo: function redo(cm) { + return cm.redo(); + }, + undoSelection: function undoSelection(cm) { + return cm.undoSelection(); + }, + redoSelection: function redoSelection(cm) { + return cm.redoSelection(); + }, + goDocStart: function goDocStart(cm) { + return cm.extendSelection(Pos(cm.firstLine(), 0)); + }, + goDocEnd: function goDocEnd(cm) { + return cm.extendSelection(Pos(cm.lastLine())); + }, + goLineStart: function goLineStart(cm) { + return cm.extendSelectionsBy(function (range) { + return lineStart(cm, range.head.line); + }, { + origin: "+move", + bias: 1 + }); + }, + goLineStartSmart: function goLineStartSmart(cm) { + return cm.extendSelectionsBy(function (range) { + return lineStartSmart(cm, range.head); + }, { + origin: "+move", + bias: 1 + }); + }, + goLineEnd: function goLineEnd(cm) { + return cm.extendSelectionsBy(function (range) { + return lineEnd(cm, range.head.line); + }, { + origin: "+move", + bias: -1 + }); + }, + goLineRight: function goLineRight(cm) { + return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({ + left: cm.display.lineDiv.offsetWidth + 100, + top: top + }, "div"); + }, sel_move); + }, + goLineLeft: function goLineLeft(cm) { + return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({ + left: 0, + top: top + }, "div"); + }, sel_move); + }, + goLineLeftSmart: function goLineLeftSmart(cm) { + return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({ + left: 0, + top: top + }, "div"); + + if (pos.ch < cm.getLine(pos.line).search(/\S/)) { + return lineStartSmart(cm, range.head); + } + + return pos; + }, sel_move); + }, + goLineUp: function goLineUp(cm) { + return cm.moveV(-1, "line"); + }, + goLineDown: function goLineDown(cm) { + return cm.moveV(1, "line"); + }, + goPageUp: function goPageUp(cm) { + return cm.moveV(-1, "page"); + }, + goPageDown: function goPageDown(cm) { + return cm.moveV(1, "page"); + }, + goCharLeft: function goCharLeft(cm) { + return cm.moveH(-1, "char"); + }, + goCharRight: function goCharRight(cm) { + return cm.moveH(1, "char"); + }, + goColumnLeft: function goColumnLeft(cm) { + return cm.moveH(-1, "column"); + }, + goColumnRight: function goColumnRight(cm) { + return cm.moveH(1, "column"); + }, + goWordLeft: function goWordLeft(cm) { + return cm.moveH(-1, "word"); + }, + goGroupRight: function goGroupRight(cm) { + return cm.moveH(1, "group"); + }, + goGroupLeft: function goGroupLeft(cm) { + return cm.moveH(-1, "group"); + }, + goWordRight: function goWordRight(cm) { + return cm.moveH(1, "word"); + }, + delCharBefore: function delCharBefore(cm) { + return cm.deleteH(-1, "char"); + }, + delCharAfter: function delCharAfter(cm) { + return cm.deleteH(1, "char"); + }, + delWordBefore: function delWordBefore(cm) { + return cm.deleteH(-1, "word"); + }, + delWordAfter: function delWordAfter(cm) { + return cm.deleteH(1, "word"); + }, + delGroupBefore: function delGroupBefore(cm) { + return cm.deleteH(-1, "group"); + }, + delGroupAfter: function delGroupAfter(cm) { + return cm.deleteH(1, "group"); + }, + indentAuto: function indentAuto(cm) { + return cm.indentSelection("smart"); + }, + indentMore: function indentMore(cm) { + return cm.indentSelection("add"); + }, + indentLess: function indentLess(cm) { + return cm.indentSelection("subtract"); + }, + insertTab: function insertTab(cm) { + return cm.replaceSelection("\t"); + }, + insertSoftTab: function insertSoftTab(cm) { + var spaces = [], + ranges = cm.listSelections(), + tabSize = cm.options.tabSize; + + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + + cm.replaceSelections(spaces); + }, + defaultTab: function defaultTab(cm) { + if (cm.somethingSelected()) { + cm.indentSelection("add"); + } else { + cm.execCommand("insertTab"); + } + }, + // Swap the two chars left and right of each selection's head. + // Move cursor behind the two swapped characters afterwards. + // + // Doesn't consider line feeds a character. + // Doesn't scan more than one line above to find a character. + // Doesn't do anything on an empty line. + // Doesn't do anything with non-empty selections. + transposeChars: function transposeChars(cm) { + return runInOp(cm, function () { + var ranges = cm.listSelections(), + newSel = []; + + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) { + continue; + } + + var cur = ranges[i].head, + line = getLine(cm.doc, cur.line).text; + + if (line) { + if (cur.ch == line.length) { + cur = new Pos(cur.line, cur.ch - 1); + } + + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + + if (prev) { + cur = new Pos(cur.line, 1); + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + prev.charAt(prev.length - 1), Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); + } + } + } + + newSel.push(new Range(cur, cur)); + } + + cm.setSelections(newSel); + }); + }, + newlineAndIndent: function newlineAndIndent(cm) { + return runInOp(cm, function () { + var sels = cm.listSelections(); + + for (var i = sels.length - 1; i >= 0; i--) { + cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); + } + + sels = cm.listSelections(); + + for (var i$1 = 0; i$1 < sels.length; i$1++) { + cm.indentLine(sels[i$1].from().line, null, true); + } + + ensureCursorVisible(cm); + }); + }, + openLine: function openLine(cm) { + return cm.replaceSelection("\n", "start"); + }, + toggleOverwrite: function toggleOverwrite(cm) { + return cm.toggleOverwrite(); + } + }; + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + + if (visual != line) { + lineN = lineNo(visual); + } + + return endOfLine(true, cm, visual, lineN, 1); + } + + function lineEnd(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLineEnd(line); + + if (visual != line) { + lineN = lineNo(visual); + } + + return endOfLine(true, cm, line, lineN, -1); + } + + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line, cm.doc.direction); + + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky); + } + + return start; + } // Run a handler that was bound to a key. + + + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + + if (!bound) { + return false; + } + } // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + + + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, + done = false; + + try { + if (cm.isReadOnly()) { + cm.state.suppressEdits = true; + } + + if (dropShift) { + cm.display.shift = false; + } + + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + + return done; + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + + if (result) { + return result; + } + } + + return cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm) || lookupKey(name, cm.options.keyMap, handle, cm); + } // Note that, despite the name, this function is also used to check + // for bound mouse clicks. + + + var stopSeq = new Delayed(); + + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + + if (seq) { + if (isModifierKey(name)) { + return "handled"; + } + + if (/\'$/.test(name)) { + cm.state.keySeq = null; + } else { + stopSeq.set(50, function () { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); + } + + if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { + return true; + } + } + + return dispatchKeyInner(cm, name, e, handle); + } + + function dispatchKeyInner(cm, name, e, handle) { + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") { + cm.state.keySeq = name; + } + + if (result == "handled") { + signalLater(cm, "keyHandled", cm, name, e); + } + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + return !!result; + } // Handle a key from the keydown event. + + + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + + if (!name) { + return false; + } + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function (b) { + return doHandleBinding(cm, b, true); + }) || dispatchKey(cm, name, e, function (b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) { + return doHandleBinding(cm, b); + } + }); + } else { + return dispatchKey(cm, name, e, function (b) { + return doHandleBinding(cm, b); + }); + } + } // Handle a key from the keypress event + + + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, function (b) { + return doHandleBinding(cm, b, true); + }); + } + + var lastStoppedKey = null; + + function onKeyDown(e) { + var cm = this; + cm.curOp.focus = activeElt(); + + if (signalDOMEvent(cm, e)) { + return; + } // IE does strange things with escape. + + + if (ie && ie_version < 11 && e.keyCode == 27) { + e.returnValue = false; + } + + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + + if (presto) { + lastStoppedKey = handled ? code : null; // Opera has no cut event... we try to at least catch the key combo + + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) { + cm.replaceSelection("", null, "cut"); + } + } // Turn mouse into crosshair when Alt is held on Mac. + + + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) { + showCrossHair(cm); + } + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) { + this.doc.sel.shift = false; + } + + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { + return; + } + + var keyCode = e.keyCode, + charCode = e.charCode; + + if (presto && keyCode == lastStoppedKey) { + lastStoppedKey = null; + e_preventDefault(e); + return; + } + + if (presto && (!e.which || e.which < 10) && handleKeyBinding(cm, e)) { + return; + } + + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); // Some browsers fire keypress events for backspace + + if (ch == "\x08") { + return; + } + + if (handleCharBinding(cm, e, ch)) { + return; + } + + cm.display.input.onKeyPress(e); + } + + var DOUBLECLICK_DELAY = 400; + + var PastClick = function PastClick(time, pos, button) { + this.time = time; + this.pos = pos; + this.button = button; + }; + + PastClick.prototype.compare = function (time, pos, button) { + return this.time + DOUBLECLICK_DELAY > time && cmp(pos, this.pos) == 0 && button == this.button; + }; + + var lastClick, lastDoubleClick; + + function clickRepeat(pos, button) { + var now = +new Date(); + + if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { + lastClick = lastDoubleClick = null; + return "triple"; + } else if (lastClick && lastClick.compare(now, pos, button)) { + lastDoubleClick = new PastClick(now, pos, button); + lastClick = null; + return "double"; + } else { + lastClick = new PastClick(now, pos, button); + lastDoubleClick = null; + return "single"; + } + } // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + + + function onMouseDown(e) { + var cm = this, + display = cm.display; + + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { + return; + } + + display.input.ensurePolled(); + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function () { + return display.scroller.draggable = true; + }, 100); + } + + return; + } + + if (clickInGutter(cm, e)) { + return; + } + + var pos = posFromMouse(cm, e), + button = e_button(e), + repeat = pos ? clickRepeat(pos, button) : "single"; + window.focus(); // #3261: make sure, that we're not starting a second selection + + if (button == 1 && cm.state.selectingText) { + cm.state.selectingText(e); + } + + if (pos && handleMappedButton(cm, button, pos, repeat, e)) { + return; + } + + if (button == 1) { + if (pos) { + leftButtonDown(cm, pos, repeat, e); + } else if (e_target(e) == display.scroller) { + e_preventDefault(e); + } + } else if (button == 2) { + if (pos) { + extendSelection(cm.doc, pos); + } + + setTimeout(function () { + return display.input.focus(); + }, 20); + } else if (button == 3) { + if (captureRightClick) { + cm.display.input.onContextMenu(e); + } else { + delayBlurEvent(cm); + } + } + } + + function handleMappedButton(cm, button, pos, repeat, event) { + var name = "Click"; + + if (repeat == "double") { + name = "Double" + name; + } else if (repeat == "triple") { + name = "Triple" + name; + } + + name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; + return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { + if (typeof bound == "string") { + bound = commands[bound]; + } + + if (!bound) { + return false; + } + + var done = false; + + try { + if (cm.isReadOnly()) { + cm.state.suppressEdits = true; + } + + done = bound(cm, pos) != Pass; + } finally { + cm.state.suppressEdits = false; + } + + return done; + }); + } + + function configureMouse(cm, repeat, event) { + var option = cm.getOption("configureMouse"); + var value = option ? option(cm, repeat, event) : {}; + + if (value.unit == null) { + var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; + value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; + } + + if (value.extend == null || cm.doc.extend) { + value.extend = cm.doc.extend || event.shiftKey; + } + + if (value.addNew == null) { + value.addNew = mac ? event.metaKey : event.ctrlKey; + } + + if (value.moveOnDrag == null) { + value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); + } + + return value; + } + + function leftButtonDown(cm, pos, repeat, event) { + if (ie) { + setTimeout(bind(ensureFocus, cm), 0); + } else { + cm.curOp.focus = activeElt(); + } + + var behavior = configureMouse(cm, repeat, event); + var sel = cm.doc.sel, + contained; + + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && repeat == "single" && (contained = sel.contains(pos)) > -1 && (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) { + leftButtonStartDrag(cm, event, pos, behavior); + } else { + leftButtonSelect(cm, event, pos, behavior); + } + } // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + + + function leftButtonStartDrag(cm, event, pos, behavior) { + var display = cm.display, + moved = false; + var dragEnd = operation(cm, function (e) { + if (webkit) { + display.scroller.draggable = false; + } + + cm.state.draggingText = false; + off(display.wrapper.ownerDocument, "mouseup", dragEnd); + off(display.wrapper.ownerDocument, "mousemove", mouseMove); + off(display.scroller, "dragstart", dragStart); + off(display.scroller, "drop", dragEnd); + + if (!moved) { + e_preventDefault(e); + + if (!behavior.addNew) { + extendSelection(cm.doc, pos, null, null, behavior.extend); + } // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + + + if (webkit || ie && ie_version == 9) { + setTimeout(function () { + display.wrapper.ownerDocument.body.focus(); + display.input.focus(); + }, 20); + } else { + display.input.focus(); + } + } + }); + + var mouseMove = function mouseMove(e2) { + moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; + }; + + var dragStart = function dragStart() { + return moved = true; + }; // Let the drag handler handle this. + + + if (webkit) { + display.scroller.draggable = true; + } + + cm.state.draggingText = dragEnd; + dragEnd.copy = !behavior.moveOnDrag; // IE's approach to draggable + + if (display.scroller.dragDrop) { + display.scroller.dragDrop(); + } + + on(display.wrapper.ownerDocument, "mouseup", dragEnd); + on(display.wrapper.ownerDocument, "mousemove", mouseMove); + on(display.scroller, "dragstart", dragStart); + on(display.scroller, "drop", dragEnd); + delayBlurEvent(cm); + setTimeout(function () { + return display.input.focus(); + }, 20); + } + + function rangeForUnit(cm, pos, unit) { + if (unit == "char") { + return new Range(pos, pos); + } + + if (unit == "word") { + return cm.findWordAt(pos); + } + + if (unit == "line") { + return new Range(Pos(pos.line, 0), _clipPos(cm.doc, Pos(pos.line + 1, 0))); + } + + var result = unit(cm, pos); + return new Range(result.from, result.to); + } // Normal selection, as opposed to text dragging. + + + function leftButtonSelect(cm, event, start, behavior) { + var display = cm.display, + doc = cm.doc; + e_preventDefault(event); + var ourRange, + ourIndex, + startSel = doc.sel, + ranges = startSel.ranges; + + if (behavior.addNew && !behavior.extend) { + ourIndex = doc.sel.contains(start); + + if (ourIndex > -1) { + ourRange = ranges[ourIndex]; + } else { + ourRange = new Range(start, start); + } + } else { + ourRange = doc.sel.primary(); + ourIndex = doc.sel.primIndex; + } + + if (behavior.unit == "rectangle") { + if (!behavior.addNew) { + ourRange = new Range(start, start); + } + + start = posFromMouse(cm, event, true, true); + ourIndex = -1; + } else { + var range$$1 = rangeForUnit(cm, start, behavior.unit); + + if (behavior.extend) { + ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); + } else { + ourRange = range$$1; + } + } + + if (!behavior.addNew) { + ourIndex = 0; + setSelection(doc, new Selection([ourRange], 0), sel_mouse); + startSel = doc.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), { + scroll: false, + origin: "*mouse" + }); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { + setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), { + scroll: false, + origin: "*mouse" + }); + startSel = doc.sel; + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) { + return; + } + + lastPos = pos; + + if (behavior.unit == "rectangle") { + var ranges = [], + tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), + right = Math.max(startCol, posCol); + + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); line <= end; line++) { + var text = getLine(doc, line).text, + leftPos = findColumn(text, left, tabSize); + + if (left == right) { + ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); + } else if (text.length > leftPos) { + ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); + } + } + + if (!ranges.length) { + ranges.push(new Range(start, start)); + } + + setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), { + origin: "*mouse", + scroll: false + }); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var range$$1 = rangeForUnit(cm, pos, behavior.unit); + var anchor = oldRange.anchor, + head; + + if (cmp(range$$1.anchor, anchor) > 0) { + head = range$$1.head; + anchor = minPos(oldRange.from(), range$$1.anchor); + } else { + head = range$$1.anchor; + anchor = maxPos(oldRange.to(), range$$1.head); + } + + var ranges$1 = startSel.ranges.slice(0); + ranges$1[ourIndex] = bidiSimplify(cm, new Range(_clipPos(doc, anchor), head)); + setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); + + if (!cur) { + return; + } + + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(); + extendTo(cur); + var visible = visibleLines(display, doc); + + if (cur.line >= visible.to || cur.line < visible.from) { + setTimeout(operation(cm, function () { + if (counter == curCount) { + extend(e); + } + }), 150); + } + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + + if (outside) { + setTimeout(operation(cm, function () { + if (counter != curCount) { + return; + } + + display.scroller.scrollTop += outside; + extend(e); + }), 50); + } + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; // If e is null or undefined we interpret this as someone trying + // to explicitly cancel the selection rather than the user + // letting go of the mouse button. + + if (e) { + e_preventDefault(e); + display.input.focus(); + } + + off(display.wrapper.ownerDocument, "mousemove", move); + off(display.wrapper.ownerDocument, "mouseup", up); + doc.history.lastSelOrigin = null; + } + + var move = operation(cm, function (e) { + if (e.buttons === 0 || !e_button(e)) { + done(e); + } else { + extend(e); + } + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(display.wrapper.ownerDocument, "mousemove", move); + on(display.wrapper.ownerDocument, "mouseup", up); + } // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + + + function bidiSimplify(cm, range$$1) { + var anchor = range$$1.anchor; + var head = range$$1.head; + var anchorLine = getLine(cm.doc, anchor.line); + + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { + return range$$1; + } + + var order = getOrder(anchorLine); + + if (!order) { + return range$$1; + } + + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), + part = order[index]; + + if (part.from != anchor.ch && part.to != anchor.ch) { + return range$$1; + } + + var boundary = index + (part.from == anchor.ch == (part.level != 1) ? 0 : 1); + + if (boundary == 0 || boundary == order.length) { + return range$$1; + } // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + + + var leftSide; + + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky); + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); + + if (headIndex == boundary - 1 || headIndex == boundary) { + leftSide = dir < 0; + } else { + leftSide = dir > 0; + } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)]; + var from = leftSide == (usePart.level == 1); + var ch = from ? usePart.from : usePart.to, + sticky = from ? "after" : "before"; + return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head); + } // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + + + function gutterEvent(cm, e, type, prevent) { + var mX, mY; + + if (e.touches) { + mX = e.touches[0].clientX; + mY = e.touches[0].clientY; + } else { + try { + mX = e.clientX; + mY = e.clientY; + } catch (e) { + return false; + } + } + + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { + return false; + } + + if (prevent) { + e_preventDefault(e); + } + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) { + return e_defaultPrevented(e); + } + + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { + var g = display.gutters.childNodes[i]; + + if (g && g.getBoundingClientRect().right >= mX) { + var line = _lineAtHeight(cm.doc, mY); + + var gutter = cm.display.gutterSpecs[i]; + signal(cm, type, cm, line, gutter.className, e); + return e_defaultPrevented(e); + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true); + } // CONTEXT MENU HANDLING + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + + + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { + return; + } + + if (signalDOMEvent(cm, e, "contextmenu")) { + return; + } + + if (!captureRightClick) { + cm.display.input.onContextMenu(e); + } + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) { + return false; + } + + return gutterEvent(cm, e, "gutterContextMenu", false); + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + var Init = { + toString: function toString() { + return "CodeMirror.Init"; + } + }; + var defaults = {}; + var optionHandlers = {}; + + function defineOptions(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + + if (handle) { + optionHandlers[name] = notOnInit ? function (cm, val, old) { + if (old != Init) { + handle(cm, val, old); + } + } : handle; + } + } + + CodeMirror.defineOption = option; // Passed to option handlers when there is no old value. + + CodeMirror.Init = Init; // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + + option("value", "", function (cm, val) { + return cm.setValue(val); + }, true); + option("mode", null, function (cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function (cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + option("lineSeparator", null, function (cm, val) { + cm.doc.lineSep = val; + + if (!val) { + return; + } + + var newBreaks = [], + lineNo = cm.doc.first; + cm.doc.iter(function (line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + + if (found == -1) { + break; + } + + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + + lineNo++; + }); + + for (var i = newBreaks.length - 1; i >= 0; i--) { + _replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); + } + }); + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + + if (old != Init) { + cm.refresh(); + } + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { + return cm.refresh(); + }, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function () { + throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME + }, true); + option("spellcheck", false, function (cm, val) { + return cm.getInputField().spellcheck = val; + }, true); + option("autocorrect", false, function (cm, val) { + return cm.getInputField().autocorrect = val; + }, true); + option("autocapitalize", false, function (cm, val) { + return cm.getInputField().autocapitalize = val; + }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + option("theme", "default", function (cm) { + themeChanged(cm); + updateGutters(cm); + }, true); + option("keyMap", "default", function (cm, val, old) { + var next = getKeyMap(val); + var prev = old != Init && getKeyMap(old); + + if (prev && prev.detach) { + prev.detach(cm, next); + } + + if (next.attach) { + next.attach(cm, prev || null); + } + }); + option("extraKeys", null); + option("configureMouse", null); + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function (cm, val) { + cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); + updateGutters(cm); + }, true); + option("fixedGutter", true, function (cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function (cm) { + return updateScrollbars(cm); + }, true); + option("scrollbarStyle", "native", function (cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function (cm, val) { + cm.display.gutterSpecs = getGutters(cm.options.gutters, val); + updateGutters(cm); + }, true); + option("firstLineNumber", 1, updateGutters, true); + option("lineNumberFormatter", function (integer) { + return integer; + }, updateGutters, true); + option("showCursorWhenSelecting", false, updateSelection, true); + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + option("pasteLinesPerSelection", true); + option("selectionsMayTouch", false); + option("readOnly", false, function (cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + } + + cm.display.input.readOnlyChanged(val); + }); + option("disableInput", false, function (cm, val) { + if (!val) { + cm.display.input.reset(); + } + }, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function (cm, val) { + return cm.doc.history.undoDepth = val; + }); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function (cm) { + return cm.refresh(); + }, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function (cm, val) { + if (!val) { + cm.display.input.resetPosition(); + } + }); + option("tabindex", null, function (cm, val) { + return cm.display.input.getField().tabIndex = val || ""; + }); + option("autofocus", null); + option("direction", "ltr", function (cm, val) { + return cm.doc.setDirection(val); + }, true); + option("phrases", null); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != Init; + + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function () { + return updateScrollbars(cm); + }, 100); + } // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + + function CodeMirror(place, options) { + var this$1 = this; + + if (!(this instanceof CodeMirror)) { + return new CodeMirror(place, options); + } + + this.options = options = options ? copyObj(options) : {}; // Determine effective options based on given values and defaults. + + copyObj(defaults, options, false); + var doc = options.value; + + if (typeof doc == "string") { + doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); + } else if (options.mode) { + doc.modeOption = options.mode; + } + + this.doc = doc; + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input, options); + display.wrapper.CodeMirror = this; + themeChanged(this); + + if (options.lineWrapping) { + this.display.wrapper.className += " CodeMirror-wrap"; + } + + initScrollbars(this); + this.state = { + keyMaps: [], + // stores maps added by addKeyMap + overlays: [], + // highlighting overlays, as added by addOverlay + modeGen: 0, + // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, + // used to disable editing during key handlers when in readOnly mode + pasteIncoming: -1, + cutIncoming: -1, + // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), + // stores highlight worker timeout + keySeq: null, + // Unfinished key sequence + specialChars: null + }; + + if (options.autofocus && !mobile) { + display.input.focus(); + } // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + + + if (ie && ie_version < 11) { + setTimeout(function () { + return this$1.display.input.reset(true); + }, 20); + } + + registerEventHandlers(this); + ensureGlobalHandlers(); + + _startOperation(this); + + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if (options.autofocus && !mobile || this.hasFocus()) { + setTimeout(bind(onFocus, this), 20); + } else { + onBlur(this); + } + + for (var opt in optionHandlers) { + if (optionHandlers.hasOwnProperty(opt)) { + optionHandlers[opt](this$1, options[opt], Init); + } + } + + maybeUpdateLineNumberWidth(this); + + if (options.finishInit) { + options.finishInit(this); + } + + for (var i = 0; i < initHooks.length; ++i) { + initHooks[i](this$1); + } + + _endOperation(this); // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + + + if (webkit && options.lineWrapping && getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") { + display.lineDiv.style.textRendering = "auto"; + } + } // The default configuration options. + + + CodeMirror.defaults = defaults; // Functions to run when options are changed. + + CodeMirror.optionHandlers = optionHandlers; // Attach the necessary event handlers when initializing the editor + + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); // Older IE's will not fire a second mousedown for a double click + + if (ie && ie_version < 11) { + on(d.scroller, "dblclick", operation(cm, function (e) { + if (signalDOMEvent(cm, e)) { + return; + } + + var pos = posFromMouse(cm, e); + + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { + return; + } + + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); + } else { + on(d.scroller, "dblclick", function (e) { + return signalDOMEvent(cm, e) || e_preventDefault(e); + }); + } // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + + + on(d.scroller, "contextmenu", function (e) { + return onContextMenu(cm, e); + }); // Used to suppress mouse event handling when a touch happens + + var touchFinished, + prevTouch = { + end: 0 + }; + + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function () { + return d.activeTouch = null; + }, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date(); + } + } + + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) { + return false; + } + + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1; + } + + function farAway(touch, other) { + if (other.left == null) { + return true; + } + + var dx = other.left - touch.left, + dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20; + } + + on(d.scroller, "touchstart", function (e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { + d.input.ensurePolled(); + clearTimeout(touchFinished); + var now = +new Date(); + d.activeTouch = { + start: now, + moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null + }; + + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function () { + if (d.activeTouch) { + d.activeTouch.moved = true; + } + }); + on(d.scroller, "touchend", function (e) { + var touch = d.activeTouch; + + if (touch && !eventInWidget(d, e) && touch.left != null && !touch.moved && new Date() - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), + range; + + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + { + range = new Range(pos, pos); + } else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + { + range = cm.findWordAt(pos); + } else // Triple tap + { + range = new Range(Pos(pos.line, 0), _clipPos(cm.doc, Pos(pos.line + 1, 0))); + } + + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + + on(d.scroller, "scroll", function () { + if (d.scroller.clientHeight) { + updateScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); // Listen to wheel events in order to try and update the viewport on time. + + on(d.scroller, "mousewheel", function (e) { + return onScrollWheel(cm, e); + }); + on(d.scroller, "DOMMouseScroll", function (e) { + return onScrollWheel(cm, e); + }); // Prevent wrapper from ever scrolling + + on(d.wrapper, "scroll", function () { + return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; + }); + d.dragFunctions = { + enter: function enter(e) { + if (!signalDOMEvent(cm, e)) { + e_stop(e); + } + }, + over: function over(e) { + if (!signalDOMEvent(cm, e)) { + onDragOver(cm, e); + e_stop(e); + } + }, + start: function start(e) { + return onDragStart(cm, e); + }, + drop: operation(cm, onDrop), + leave: function leave(e) { + if (!signalDOMEvent(cm, e)) { + clearDragCursor(cm); + } + } + }; + var inp = d.input.getField(); + on(inp, "keyup", function (e) { + return onKeyUp.call(cm, e); + }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", function (e) { + return onFocus(cm, e); + }); + on(inp, "blur", function (e) { + return onBlur(cm, e); + }); + } + + var initHooks = []; + + CodeMirror.defineInitHook = function (f) { + return initHooks.push(f); + }; // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + + + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, + state; + + if (how == null) { + how = "add"; + } + + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) { + how = "prev"; + } else { + state = getContextBefore(cm, n).state; + } + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), + curSpace = countColumn(line.text, null, tabSize); + + if (line.stateAfter) { + line.stateAfter = null; + } + + var curSpaceString = line.text.match(/^\s*/)[0], + indentation; + + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + + if (indentation == Pass || indentation > 150) { + if (!aggressive) { + return; + } + + how = "prev"; + } + } + + if (how == "prev") { + if (n > doc.first) { + indentation = countColumn(getLine(doc, n - 1).text, null, tabSize); + } else { + indentation = 0; + } + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + + indentation = Math.max(0, indentation); + var indentString = "", + pos = 0; + + if (cm.options.indentWithTabs) { + for (var i = Math.floor(indentation / tabSize); i; --i) { + pos += tabSize; + indentString += "\t"; + } + } + + if (pos < indentation) { + indentString += spaceStr(indentation - pos); + } + + if (indentString != curSpaceString) { + _replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + + line.stateAfter = null; + return true; + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { + var range = doc.sel.ranges[i$1]; + + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos$1 = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); + break; + } + } + } + } // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + + + var lastCopied = null; + + function setLastCopied(newLastCopied) { + lastCopied = newLastCopied; + } + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + + if (!sel) { + sel = doc.sel; + } + + var recent = +new Date() - 200; + var paste = origin == "paste" || cm.state.pasteIncoming > recent; + var textLines = splitLinesAuto(inserted), + multiPaste = null; // When pasting N lines into N selections, insert one line per selection + + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + + for (var i = 0; i < lastCopied.text.length; i++) { + multiPaste.push(doc.splitLines(lastCopied.text[i])); + } + } + } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { + multiPaste = map(textLines, function (l) { + return [l]; + }); + } + } + + var updateInput = cm.curOp.updateInput; // Normal behavior is to insert the new text into every selection + + for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { + var range$$1 = sel.ranges[i$1]; + var from = range$$1.from(), + to = range$$1.to(); + + if (range$$1.empty()) { + if (deleted && deleted > 0) // Handle deletion + { + from = Pos(from.line, from.ch - deleted); + } else if (cm.state.overwrite && !paste) // Handle overwrite + { + to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); + } else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) { + from = to = Pos(from.line, 0); + } + } + + var changeEvent = { + from: from, + to: to, + text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input") + }; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + + if (inserted && !paste) { + triggerElectric(cm, inserted); + } + + ensureCursorVisible(cm); + + if (cm.curOp.updateInput < 2) { + cm.curOp.updateInput = updateInput; + } + + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = -1; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text"); + + if (pasted) { + e.preventDefault(); + + if (!cm.isReadOnly() && !cm.options.disableInput) { + runInOp(cm, function () { + return applyTextInput(cm, pasted, 0, null, "paste"); + }); + } + + return true; + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) { + return; + } + + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range$$1 = sel.ranges[i]; + + if (range$$1.head.ch > 100 || i && sel.ranges[i - 1].head.line == range$$1.head.line) { + continue; + } + + var mode = cm.getModeAt(range$$1.head); + var indented = false; + + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) { + if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range$$1.head.line, "smart"); + break; + } + } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch))) { + indented = indentLine(cm, range$$1.head.line, "smart"); + } + } + + if (indented) { + signalLater(cm, "electricInput", cm, range$$1.head.line); + } + } + } + + function copyableRanges(cm) { + var text = [], + ranges = []; + + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = { + anchor: Pos(line, 0), + head: Pos(line + 1, 0) + }; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + + return { + text: text, + ranges: ranges + }; + } + + function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { + field.setAttribute("autocorrect", autocorrect ? "" : "off"); + field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); + field.setAttribute("spellcheck", !!spellcheck); + } + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + + if (webkit) { + te.style.width = "1000px"; + } else { + te.setAttribute("wrap", "off"); + } // If border: 0; -- iOS fails to open keyboard (issue #1287) + + + if (ios) { + te.style.border = "1px solid black"; + } + + disableBrowserMagic(te); + return div; + } // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + + function addEditorMethods(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + var helpers = CodeMirror.helpers = {}; + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function focus() { + window.focus(); + this.display.input.focus(); + }, + setOption: function setOption(option, value) { + var options = this.options, + old = options[option]; + + if (options[option] == value && option != "mode") { + return; + } + + options[option] = value; + + if (optionHandlers.hasOwnProperty(option)) { + operation(this, optionHandlers[option])(this, value, old); + } + + signal(this, "optionChange", this, option); + }, + getOption: function getOption(option) { + return this.options[option]; + }, + getDoc: function getDoc() { + return this.doc; + }, + addKeyMap: function addKeyMap(map$$1, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1)); + }, + removeKeyMap: function removeKeyMap(map$$1) { + var maps = this.state.keyMaps; + + for (var i = 0; i < maps.length; ++i) { + if (maps[i] == map$$1 || maps[i].name == map$$1) { + maps.splice(i, 1); + return true; + } + } + }, + addOverlay: methodOp(function (spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + + if (mode.startState) { + throw new Error("Overlays may not be stateful."); + } + + insertSorted(this.state.overlays, { + mode: mode, + modeSpec: spec, + opaque: options && options.opaque, + priority: options && options.priority || 0 + }, function (overlay) { + return overlay.priority; + }); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function (spec) { + var this$1 = this; + var overlays = this.state.overlays; + + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this$1.state.modeGen++; + regChange(this$1); + return; + } + } + }), + indentLine: methodOp(function (n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) { + dir = this.options.smartIndent ? "smart" : "prev"; + } else { + dir = dir ? "add" : "subtract"; + } + } + + if (isLine(this.doc, n)) { + indentLine(this, n, dir, aggressive); + } + }), + indentSelection: methodOp(function (how) { + var this$1 = this; + var ranges = this.doc.sel.ranges, + end = -1; + + for (var i = 0; i < ranges.length; i++) { + var range$$1 = ranges[i]; + + if (!range$$1.empty()) { + var from = range$$1.from(), + to = range$$1.to(); + var start = Math.max(end, from.line); + end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + + for (var j = start; j < end; ++j) { + indentLine(this$1, j, how); + } + + var newRanges = this$1.doc.sel.ranges; + + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) { + replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); + } + } else if (range$$1.head.line > end) { + indentLine(this$1, range$$1.head.line, how, true); + end = range$$1.head.line; + + if (i == this$1.doc.sel.primIndex) { + ensureCursorVisible(this$1); + } + } + } + }), + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function getTokenAt(pos, precise) { + return takeToken(this, pos, precise); + }, + getLineTokens: function getLineTokens(line, precise) { + return takeToken(this, Pos(line), precise, true); + }, + getTokenTypeAt: function getTokenTypeAt(pos) { + pos = _clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, + after = (styles.length - 1) / 2, + ch = pos.ch; + var type; + + if (ch == 0) { + type = styles[2]; + } else { + for (;;) { + var mid = before + after >> 1; + + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { + after = mid; + } else if (styles[mid * 2 + 1] < ch) { + before = mid + 1; + } else { + type = styles[mid * 2 + 2]; + break; + } + } + } + + var cut = type ? type.indexOf("overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); + }, + getModeAt: function getModeAt(pos) { + var mode = this.doc.mode; + + if (!mode.innerMode) { + return mode; + } + + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; + }, + getHelper: function getHelper(pos, type) { + return this.getHelpers(pos, type)[0]; + }, + getHelpers: function getHelpers(pos, type) { + var this$1 = this; + var found = []; + + if (!helpers.hasOwnProperty(type)) { + return found; + } + + var help = helpers[type], + mode = this.getModeAt(pos); + + if (typeof mode[type] == "string") { + if (help[mode[type]]) { + found.push(help[mode[type]]); + } + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + + if (val) { + found.push(val); + } + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + + for (var i$1 = 0; i$1 < help._global.length; i$1++) { + var cur = help._global[i$1]; + + if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) { + found.push(cur.val); + } + } + + return found; + }, + getStateAfter: function getStateAfter(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1 : line); + return getContextBefore(this, line + 1, precise).state; + }, + cursorCoords: function cursorCoords(start, mode) { + var pos, + range$$1 = this.doc.sel.primary(); + + if (start == null) { + pos = range$$1.head; + } else if (_typeof(start) == "object") { + pos = _clipPos(this.doc, start); + } else { + pos = start ? range$$1.from() : range$$1.to(); + } + + return _cursorCoords(this, pos, mode || "page"); + }, + charCoords: function charCoords(pos, mode) { + return _charCoords(this, _clipPos(this.doc, pos), mode || "page"); + }, + coordsChar: function coordsChar(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return _coordsChar(this, coords.left, coords.top); + }, + lineAtHeight: function lineAtHeight(height, mode) { + height = fromCoordSystem(this, { + top: height, + left: 0 + }, mode || "page").top; + return _lineAtHeight(this.doc, height + this.display.viewOffset); + }, + heightAtLine: function heightAtLine(line, mode, includeWidgets) { + var end = false, + lineObj; + + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + + if (line < this.doc.first) { + line = this.doc.first; + } else if (line > last) { + line = last; + end = true; + } + + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + + return intoCoordSystem(this, lineObj, { + top: 0, + left: 0 + }, mode || "page", includeWidgets || end).top + (end ? this.doc.height - _heightAtLine(lineObj) : 0); + }, + defaultTextHeight: function defaultTextHeight() { + return textHeight(this.display); + }, + defaultCharWidth: function defaultCharWidth() { + return charWidth(this.display); + }, + getViewport: function getViewport() { + return { + from: this.display.viewFrom, + to: this.display.viewTo + }; + }, + addWidget: function addWidget(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = _cursorCoords(this, _clipPos(this.doc, pos)); + var top = pos.bottom, + left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); // Default to positioning above (if specified and possible); otherwise default to positioning below + + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) { + top = pos.top - node.offsetHeight; + } else if (pos.bottom + node.offsetHeight <= vspace) { + top = pos.bottom; + } + + if (left + node.offsetWidth > hspace) { + left = hspace - node.offsetWidth; + } + } + + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") { + left = 0; + } else if (horiz == "middle") { + left = (display.sizer.clientWidth - node.offsetWidth) / 2; + } + + node.style.left = left + "px"; + } + + if (scroll) { + scrollIntoView(this, { + left: left, + top: top, + right: left + node.offsetWidth, + bottom: top + node.offsetHeight + }); + } + }, + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + triggerOnMouseDown: methodOp(onMouseDown), + execCommand: function execCommand(cmd) { + if (commands.hasOwnProperty(cmd)) { + return commands[cmd].call(null, this); + } + }, + triggerElectric: methodOp(function (text) { + triggerElectric(this, text); + }), + findPosH: function findPosH(from, amount, unit, visually) { + var this$1 = this; + var dir = 1; + + if (amount < 0) { + dir = -1; + amount = -amount; + } + + var cur = _clipPos(this.doc, from); + + for (var i = 0; i < amount; ++i) { + cur = _findPosH(this$1.doc, cur, dir, unit, visually); + + if (cur.hitSide) { + break; + } + } + + return cur; + }, + moveH: methodOp(function (dir, unit) { + var this$1 = this; + this.extendSelectionsBy(function (range$$1) { + if (this$1.display.shift || this$1.doc.extend || range$$1.empty()) { + return _findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually); + } else { + return dir < 0 ? range$$1.from() : range$$1.to(); + } + }, sel_move); + }), + deleteH: methodOp(function (dir, unit) { + var sel = this.doc.sel, + doc = this.doc; + + if (sel.somethingSelected()) { + doc.replaceSelection("", null, "+delete"); + } else { + deleteNearSelection(this, function (range$$1) { + var other = _findPosH(doc, range$$1.head, dir, unit, false); + + return dir < 0 ? { + from: other, + to: range$$1.head + } : { + from: range$$1.head, + to: other + }; + }); + } + }), + findPosV: function findPosV(from, amount, unit, goalColumn) { + var this$1 = this; + var dir = 1, + x = goalColumn; + + if (amount < 0) { + dir = -1; + amount = -amount; + } + + var cur = _clipPos(this.doc, from); + + for (var i = 0; i < amount; ++i) { + var coords = _cursorCoords(this$1, cur, "div"); + + if (x == null) { + x = coords.left; + } else { + coords.left = x; + } + + cur = _findPosV(this$1, coords, dir, unit); + + if (cur.hitSide) { + break; + } + } + + return cur; + }, + moveV: methodOp(function (dir, unit) { + var this$1 = this; + var doc = this.doc, + goals = []; + var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function (range$$1) { + if (collapse) { + return dir < 0 ? range$$1.from() : range$$1.to(); + } + + var headPos = _cursorCoords(this$1, range$$1.head, "div"); + + if (range$$1.goalColumn != null) { + headPos.left = range$$1.goalColumn; + } + + goals.push(headPos.left); + + var pos = _findPosV(this$1, headPos, dir, unit); + + if (unit == "page" && range$$1 == doc.sel.primary()) { + addToScrollTop(this$1, _charCoords(this$1, pos, "div").top - headPos.top); + } + + return pos; + }, sel_move); + + if (goals.length) { + for (var i = 0; i < doc.sel.ranges.length; i++) { + doc.sel.ranges[i].goalColumn = goals[i]; + } + } + }), + // Find the word at the given position (as returned by coordsChar). + findWordAt: function findWordAt(pos) { + var doc = this.doc, + line = getLine(doc, pos.line).text; + var start = pos.ch, + end = pos.ch; + + if (line) { + var helper = this.getHelper(pos, "wordChars"); + + if ((pos.sticky == "before" || end == line.length) && start) { + --start; + } else { + ++end; + } + + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) ? function (ch) { + return isWordChar(ch, helper); + } : /\s/.test(startChar) ? function (ch) { + return /\s/.test(ch); + } : function (ch) { + return !/\s/.test(ch) && !isWordChar(ch); + }; + + while (start > 0 && check(line.charAt(start - 1))) { + --start; + } + + while (end < line.length && check(line.charAt(end))) { + ++end; + } + } + + return new Range(Pos(pos.line, start), Pos(pos.line, end)); + }, + toggleOverwrite: function toggleOverwrite(value) { + if (value != null && value == this.state.overwrite) { + return; + } + + if (this.state.overwrite = !this.state.overwrite) { + addClass(this.display.cursorDiv, "CodeMirror-overwrite"); + } else { + rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); + } + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function hasFocus() { + return this.display.input.getField() == activeElt(); + }, + isReadOnly: function isReadOnly() { + return !!(this.options.readOnly || this.doc.cantEdit); + }, + scrollTo: methodOp(function (x, y) { + scrollToCoords(this, x, y); + }), + getScrollInfo: function getScrollInfo() { + var scroller = this.display.scroller; + return { + left: scroller.scrollLeft, + top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), + clientWidth: displayWidth(this) + }; + }, + scrollIntoView: methodOp(function (range$$1, margin) { + if (range$$1 == null) { + range$$1 = { + from: this.doc.sel.primary().head, + to: null + }; + + if (margin == null) { + margin = this.options.cursorScrollMargin; + } + } else if (typeof range$$1 == "number") { + range$$1 = { + from: Pos(range$$1, 0), + to: null + }; + } else if (range$$1.from == null) { + range$$1 = { + from: range$$1, + to: null + }; + } + + if (!range$$1.to) { + range$$1.to = range$$1.from; + } + + range$$1.margin = margin || 0; + + if (range$$1.from.line != null) { + scrollToRange(this, range$$1); + } else { + scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin); + } + }), + setSize: methodOp(function (width, height) { + var this$1 = this; + + var interpret = function interpret(val) { + return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; + }; + + if (width != null) { + this.display.wrapper.style.width = interpret(width); + } + + if (height != null) { + this.display.wrapper.style.height = interpret(height); + } + + if (this.options.lineWrapping) { + clearLineMeasurementCache(this); + } + + var lineNo$$1 = this.display.viewFrom; + this.doc.iter(lineNo$$1, this.display.viewTo, function (line) { + if (line.widgets) { + for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].noHScroll) { + regLineChange(this$1, lineNo$$1, "widget"); + break; + } + } + } + + ++lineNo$$1; + }); + this.curOp.forceUpdate = true; + signal(this, "refresh", this); + }), + operation: function operation(f) { + return runInOp(this, f); + }, + startOperation: function startOperation() { + return _startOperation(this); + }, + endOperation: function endOperation() { + return _endOperation(this); + }, + refresh: methodOp(function () { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this.display); + + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) { + estimateLineHeights(this); + } + + signal(this, "refresh", this); + }), + swapDoc: methodOp(function (doc) { + var old = this.doc; + old.cm = null; // Cancel the current text selection if any (#5821) + + if (this.state.selectingText) { + this.state.selectingText(); + } + + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + scrollToCoords(this, doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old; + }), + phrase: function phrase(phraseText) { + var phrases = this.options.phrases; + return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText; + }, + getInputField: function getInputField() { + return this.display.input.getField(); + }, + getWrapperElement: function getWrapperElement() { + return this.display.wrapper; + }, + getScrollerElement: function getScrollerElement() { + return this.display.scroller; + }, + getGutterElement: function getGutterElement() { + return this.display.gutters; + } + }; + eventMixin(CodeMirror); + + CodeMirror.registerHelper = function (type, name, value) { + if (!helpers.hasOwnProperty(type)) { + helpers[type] = CodeMirror[type] = { + _global: [] + }; + } + + helpers[type][name] = value; + }; + + CodeMirror.registerGlobalHelper = function (type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + + helpers[type]._global.push({ + pred: predicate, + val: value + }); + }; + } // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "char", "column" (like char, but doesn't + // cross line boundaries), "word" (across next word), or "group" (to + // the start of next group of word or non-word-non-whitespace + // chars). The visually param controls whether, in right-to-left + // text, direction 1 means to move towards the next index in the + // string, or towards the character to the right of the current + // position. The resulting position will have a hitSide=true + // property if it reached the end of the document. + + + function _findPosH(doc, pos, dir, unit, visually) { + var oldPos = pos; + var origDir = dir; + var lineObj = getLine(doc, pos.line); + + function findNextLine() { + var l = pos.line + dir; + + if (l < doc.first || l >= doc.first + doc.size) { + return false; + } + + pos = new Pos(l, pos.ch, pos.sticky); + return lineObj = getLine(doc, l); + } + + function moveOnce(boundToLine) { + var next; + + if (visually) { + next = moveVisually(doc.cm, lineObj, pos, dir); + } else { + next = moveLogically(lineObj, pos, dir); + } + + if (next == null) { + if (!boundToLine && findNextLine()) { + pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); + } else { + return false; + } + } else { + pos = next; + } + + return true; + } + + if (unit == "char") { + moveOnce(); + } else if (unit == "column") { + moveOnce(true); + } else if (unit == "word" || unit == "group") { + var sawType = null, + group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) { + break; + } + + var cur = lineObj.text.charAt(pos.ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" : group && cur == "\n" ? "n" : !group || /\s/.test(cur) ? null : "p"; + + if (group && !first && !type) { + type = "s"; + } + + if (sawType && sawType != type) { + if (dir < 0) { + dir = 1; + moveOnce(); + pos.sticky = "after"; + } + + break; + } + + if (type) { + sawType = type; + } + + if (dir > 0 && !moveOnce(!first)) { + break; + } + } + } + + var result = skipAtomic(doc, pos, oldPos, origDir, true); + + if (equalCursorPos(oldPos, result)) { + result.hitSide = true; + } + + return result; + } // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + + + function _findPosV(cm, pos, dir, unit) { + var doc = cm.doc, + x = pos.left, + y; + + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); + y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + + var target; + + for (;;) { + target = _coordsChar(cm, x, y); + + if (!target.outside) { + break; + } + + if (dir < 0 ? y <= 0 : y >= doc.height) { + target.hitSide = true; + break; + } + + y += dir * 5; + } + + return target; + } // CONTENTEDITABLE INPUT STYLE + + + var ContentEditableInput = function ContentEditableInput(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.composing = null; + this.gracePeriod = false; + this.readDOMTimeout = null; + }; + + ContentEditableInput.prototype.init = function (display) { + var this$1 = this; + var input = this, + cm = input.cm; + var div = input.div = display.lineDiv; + disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); + on(div, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { + return; + } // IE doesn't fire input events, so we schedule a read for the pasted content in this way + + + if (ie_version <= 11) { + setTimeout(operation(cm, function () { + return this$1.updateFromDOM(); + }), 20); + } + }); + on(div, "compositionstart", function (e) { + this$1.composing = { + data: e.data, + done: false + }; + }); + on(div, "compositionupdate", function (e) { + if (!this$1.composing) { + this$1.composing = { + data: e.data, + done: false + }; + } + }); + on(div, "compositionend", function (e) { + if (this$1.composing) { + if (e.data != this$1.composing.data) { + this$1.readFromDOMSoon(); + } + + this$1.composing.done = true; + } + }); + on(div, "touchstart", function () { + return input.forceCompositionEnd(); + }); + on(div, "input", function () { + if (!this$1.composing) { + this$1.readFromDOMSoon(); + } + }); + + function onCopyCut(e) { + if (signalDOMEvent(cm, e)) { + return; + } + + if (cm.somethingSelected()) { + setLastCopied({ + lineWise: false, + text: cm.getSelections() + }); + + if (e.type == "cut") { + cm.replaceSelection("", null, "cut"); + } + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + setLastCopied({ + lineWise: true, + text: ranges.text + }); + + if (e.type == "cut") { + cm.operation(function () { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + + if (e.clipboardData) { + e.clipboardData.clearData(); + var content = lastCopied.text.join("\n"); // iOS exposes the clipboard API, but seems to discard content inserted into it + + e.clipboardData.setData("Text", content); + + if (e.clipboardData.getData("Text") == content) { + e.preventDefault(); + return; + } + } // Old-fashioned briefly-focus-a-textarea hack + + + var kludge = hiddenTextarea(), + te = kludge.firstChild; + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = document.activeElement; + selectInput(te); + setTimeout(function () { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + + if (hadFocus == div) { + input.showPrimarySelection(); + } + }, 50); + } + + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }; + + ContentEditableInput.prototype.prepareSelection = function () { + var result = prepareSelection(this.cm, false); + result.focus = this.cm.state.focused; + return result; + }; + + ContentEditableInput.prototype.showSelection = function (info, takeFocus) { + if (!info || !this.cm.display.view.length) { + return; + } + + if (info.focus || takeFocus) { + this.showPrimarySelection(); + } + + this.showMultipleSelections(info); + }; + + ContentEditableInput.prototype.getSelection = function () { + return this.cm.display.wrapper.ownerDocument.getSelection(); + }; + + ContentEditableInput.prototype.showPrimarySelection = function () { + var sel = this.getSelection(), + cm = this.cm, + prim = cm.doc.sel.primary(); + var from = prim.from(), + to = prim.to(); + + if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { + sel.removeAllRanges(); + return; + } + + var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); + + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && cmp(minPos(curAnchor, curFocus), from) == 0 && cmp(maxPos(curAnchor, curFocus), to) == 0) { + return; + } + + var view = cm.display.view; + var start = from.line >= cm.display.viewFrom && posToDOM(cm, from) || { + node: view[0].measure.map[2], + offset: 0 + }; + var end = to.line < cm.display.viewTo && posToDOM(cm, to); + + if (!end) { + var measure = view[view.length - 1].measure; + var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = { + node: map$$1[map$$1.length - 1], + offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3] + }; + } + + if (!start || !end) { + sel.removeAllRanges(); + return; + } + + var old = sel.rangeCount && sel.getRangeAt(0), + rng; + + try { + rng = range(start.node, start.offset, end.offset, end.node); + } catch (e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + + + if (rng) { + if (!gecko && cm.state.focused) { + sel.collapse(start.node, start.offset); + + if (!rng.collapsed) { + sel.removeAllRanges(); + sel.addRange(rng); + } + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + + if (old && sel.anchorNode == null) { + sel.addRange(old); + } else if (gecko) { + this.startGracePeriod(); + } + } + + this.rememberSelection(); + }; + + ContentEditableInput.prototype.startGracePeriod = function () { + var this$1 = this; + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function () { + this$1.gracePeriod = false; + + if (this$1.selectionChanged()) { + this$1.cm.operation(function () { + return this$1.cm.curOp.selectionChanged = true; + }); + } + }, 20); + }; + + ContentEditableInput.prototype.showMultipleSelections = function (info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }; + + ContentEditableInput.prototype.rememberSelection = function () { + var sel = this.getSelection(); + this.lastAnchorNode = sel.anchorNode; + this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; + this.lastFocusOffset = sel.focusOffset; + }; + + ContentEditableInput.prototype.selectionInEditor = function () { + var sel = this.getSelection(); + + if (!sel.rangeCount) { + return false; + } + + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node); + }; + + ContentEditableInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor") { + if (!this.selectionInEditor()) { + this.showSelection(this.prepareSelection(), true); + } + + this.div.focus(); + } + }; + + ContentEditableInput.prototype.blur = function () { + this.div.blur(); + }; + + ContentEditableInput.prototype.getField = function () { + return this.div; + }; + + ContentEditableInput.prototype.supportsTouch = function () { + return true; + }; + + ContentEditableInput.prototype.receivedFocus = function () { + var input = this; + + if (this.selectionInEditor()) { + this.pollSelection(); + } else { + runInOp(this.cm, function () { + return input.cm.curOp.selectionChanged = true; + }); + } + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + + this.polling.set(this.cm.options.pollInterval, poll); + }; + + ContentEditableInput.prototype.selectionChanged = function () { + var sel = this.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset; + }; + + ContentEditableInput.prototype.pollSelection = function () { + if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { + return; + } + + var sel = this.getSelection(), + cm = this.cm; // On Android Chrome (version 56, at least), backspacing into an + // uneditable block element will put the cursor in that element, + // and then, because it's not editable, hide the virtual keyboard. + // Because Android doesn't allow us to actually detect backspace + // presses in a sane way, this code checks for when that happens + // and simulates a backspace press in this case. + + if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { + this.cm.triggerOnKeyDown({ + type: "keydown", + keyCode: 8, + preventDefault: Math.abs + }); + this.blur(); + this.focus(); + return; + } + + if (this.composing) { + return; + } + + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + + if (anchor && head) { + runInOp(cm, function () { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + + if (anchor.bad || head.bad) { + cm.curOp.selectionChanged = true; + } + }); + } + }; + + ContentEditableInput.prototype.pollContent = function () { + if (this.readDOMTimeout != null) { + clearTimeout(this.readDOMTimeout); + this.readDOMTimeout = null; + } + + var cm = this.cm, + display = cm.display, + sel = cm.doc.sel.primary(); + var from = sel.from(), + to = sel.to(); + + if (from.ch == 0 && from.line > cm.firstLine()) { + from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); + } + + if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) { + to = Pos(to.line + 1, 0); + } + + if (from.line < display.viewFrom || to.line > display.viewTo - 1) { + return false; + } + + var fromIndex, fromLine, fromNode; + + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + fromLine = lineNo(display.view[0].line); + fromNode = display.view[0].node; + } else { + fromLine = lineNo(display.view[fromIndex].line); + fromNode = display.view[fromIndex - 1].node.nextSibling; + } + + var toIndex = findViewIndex(cm, to.line); + var toLine, toNode; + + if (toIndex == display.view.length - 1) { + toLine = display.viewTo - 1; + toNode = display.lineDiv.lastChild; + } else { + toLine = lineNo(display.view[toIndex + 1].line) - 1; + toNode = display.view[toIndex + 1].node.previousSibling; + } + + if (!fromNode) { + return false; + } + + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { + newText.pop(); + oldText.pop(); + toLine--; + } else if (newText[0] == oldText[0]) { + newText.shift(); + oldText.shift(); + fromLine++; + } else { + break; + } + } + + var cutFront = 0, + cutEnd = 0; + var newTop = newText[0], + oldTop = oldText[0], + maxCutFront = Math.min(newTop.length, oldTop.length); + + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) { + ++cutFront; + } + + var newBot = lst(newText), + oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), oldBot.length - (oldText.length == 1 ? cutFront : 0)); + + while (cutEnd < maxCutEnd && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + ++cutEnd; + } // Try to move start of change to start of selection if ambiguous + + + if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { + while (cutFront && cutFront > from.ch && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + cutFront--; + cutEnd++; + } + } + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); + newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + _replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + + return true; + } + }; + + ContentEditableInput.prototype.ensurePolled = function () { + this.forceCompositionEnd(); + }; + + ContentEditableInput.prototype.reset = function () { + this.forceCompositionEnd(); + }; + + ContentEditableInput.prototype.forceCompositionEnd = function () { + if (!this.composing) { + return; + } + + clearTimeout(this.readDOMTimeout); + this.composing = null; + this.updateFromDOM(); + this.div.blur(); + this.div.focus(); + }; + + ContentEditableInput.prototype.readFromDOMSoon = function () { + var this$1 = this; + + if (this.readDOMTimeout != null) { + return; + } + + this.readDOMTimeout = setTimeout(function () { + this$1.readDOMTimeout = null; + + if (this$1.composing) { + if (this$1.composing.done) { + this$1.composing = null; + } else { + return; + } + } + + this$1.updateFromDOM(); + }, 80); + }; + + ContentEditableInput.prototype.updateFromDOM = function () { + var this$1 = this; + + if (this.cm.isReadOnly() || !this.pollContent()) { + runInOp(this.cm, function () { + return regChange(this$1.cm); + }); + } + }; + + ContentEditableInput.prototype.setUneditable = function (node) { + node.contentEditable = "false"; + }; + + ContentEditableInput.prototype.onKeyPress = function (e) { + if (e.charCode == 0 || this.composing) { + return; + } + + e.preventDefault(); + + if (!this.cm.isReadOnly()) { + operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); + } + }; + + ContentEditableInput.prototype.readOnlyChanged = function (val) { + this.div.contentEditable = String(val != "nocursor"); + }; + + ContentEditableInput.prototype.onContextMenu = function () {}; + + ContentEditableInput.prototype.resetPosition = function () {}; + + ContentEditableInput.prototype.needsContentAttribute = true; + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + + if (!view || view.hidden) { + return null; + } + + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + var order = getOrder(line, cm.doc.direction), + side = "left"; + + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result; + } + + function isInGutter(node) { + for (var scan = node; scan; scan = scan.parentNode) { + if (/CodeMirror-gutter-wrapper/.test(scan.className)) { + return true; + } + } + + return false; + } + + function badPos(pos, bad) { + if (bad) { + pos.bad = true; + } + + return pos; + } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", + closing = false, + lineSep = cm.doc.lineSeparator(), + extraLinebreak = false; + + function recognizeMarker(id) { + return function (marker) { + return marker.id == id; + }; + } + + function close() { + if (closing) { + text += lineSep; + + if (extraLinebreak) { + text += lineSep; + } + + closing = extraLinebreak = false; + } + } + + function addText(str) { + if (str) { + close(); + text += str; + } + } + + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + + if (cmText) { + addText(cmText); + return; + } + + var markerID = node.getAttribute("cm-marker"), + range$$1; + + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + + if (found.length && (range$$1 = found[0].find(0))) { + addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); + } + + return; + } + + if (node.getAttribute("contenteditable") == "false") { + return; + } + + var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); + + if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { + return; + } + + if (isBlock) { + close(); + } + + for (var i = 0; i < node.childNodes.length; i++) { + walk(node.childNodes[i]); + } + + if (/^(pre|p)$/i.test(node.nodeName)) { + extraLinebreak = true; + } + + if (isBlock) { + closing = true; + } + } else if (node.nodeType == 3) { + addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); + } + } + + for (;;) { + walk(from); + + if (from == to) { + break; + } + + from = from.nextSibling; + extraLinebreak = false; + } + + return text; + } + + function domToPos(cm, node, offset) { + var lineNode; + + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + + if (!lineNode) { + return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true); + } + + node = null; + offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) { + return null; + } + + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { + break; + } + } + } + + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + + if (lineView.node == lineNode) { + return locateNodeInLineView(lineView, node, offset); + } + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, + bad = false; + + if (!node || !contains(wrapper, node)) { + return badPos(Pos(lineNo(lineView.line), 0), true); + } + + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad); + } + } + + var textNode = node.nodeType == 3 ? node : null, + topNode = node; + + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + + if (offset) { + offset = textNode.nodeValue.length; + } + } + + while (topNode.parentNode != wrapper) { + topNode = topNode.parentNode; + } + + var measure = lineView.measure, + maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map$$1 = i < 0 ? measure.map : maps[i]; + + for (var j = 0; j < map$$1.length; j += 3) { + var curNode = map$$1[j + 2]; + + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map$$1[j] + offset; + + if (offset < 0 || curNode != textNode) { + ch = map$$1[j + (offset ? 1 : 0)]; + } + + return Pos(line, ch); + } + } + } + } + + var found = find(textNode, topNode, offset); + + if (found) { + return badPos(found, bad); + } // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + + + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + + if (found) { + return badPos(Pos(found.line, found.ch - dist), bad); + } else { + dist += after.textContent.length; + } + } + + for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + + if (found) { + return badPos(Pos(found.line, found.ch + dist$1), bad); + } else { + dist$1 += before.textContent.length; + } + } + } // TEXTAREA INPUT STYLE + + + var TextareaInput = function TextareaInput(cm) { + this.cm = cm; // See input.poll and input.reset + + this.prevInput = ""; // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + + this.pollingFast = false; // Self-resetting timeout for the poller + + this.polling = new Delayed(); // Used to work around IE issue with selection being forgotten when focus moves away from textarea + + this.hasSelection = false; + this.composing = null; + }; + + TextareaInput.prototype.init = function (display) { + var this$1 = this; + var input = this, + cm = this.cm; + this.createField(display); + var te = this.textarea; + display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + + if (ios) { + te.style.width = "0px"; + } + + on(te, "input", function () { + if (ie && ie_version >= 9 && this$1.hasSelection) { + this$1.hasSelection = null; + } + + input.poll(); + }); + on(te, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { + return; + } + + cm.state.pasteIncoming = +new Date(); + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) { + return; + } + + if (cm.somethingSelected()) { + setLastCopied({ + lineWise: false, + text: cm.getSelections() + }); + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + setLastCopied({ + lineWise: true, + text: ranges.text + }); + + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + + if (e.type == "cut") { + cm.state.cutIncoming = +new Date(); + } + } + + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + on(display.scroller, "paste", function (e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { + return; + } + + if (!te.dispatchEvent) { + cm.state.pasteIncoming = +new Date(); + input.focus(); + return; + } // Pass the `paste` event to the textarea so it's handled by its event listener. + + + var event = new Event("paste"); + event.clipboardData = e.clipboardData; + te.dispatchEvent(event); + }); // Prevent normal selection in the editor (we handle our own) + + on(display.lineSpace, "selectstart", function (e) { + if (!eventInWidget(display, e)) { + e_preventDefault(e); + } + }); + on(te, "compositionstart", function () { + var start = cm.getCursor("from"); + + if (input.composing) { + input.composing.range.clear(); + } + + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), { + className: "CodeMirror-composing" + }) + }; + }); + on(te, "compositionend", function () { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }; + + TextareaInput.prototype.createField = function (_display) { + // Wraps and hides input textarea + this.wrapper = hiddenTextarea(); // The semihidden textarea that is focused when the editor is + // focused, and receives input. + + this.textarea = this.wrapper.firstChild; + }; + + TextareaInput.prototype.prepareSelection = function () { + // Redraw the selection and/or cursor + var cm = this.cm, + display = cm.display, + doc = cm.doc; + var result = prepareSelection(cm); // Move the hidden textarea near the cursor to prevent scrolling artifacts + + if (cm.options.moveInputWithCursor) { + var headPos = _cursorCoords(cm, doc.sel.primary().head, "div"); + + var wrapOff = display.wrapper.getBoundingClientRect(), + lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, headPos.left + lineOff.left - wrapOff.left)); + } + + return result; + }; + + TextareaInput.prototype.showSelection = function (drawn) { + var cm = this.cm, + display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }; // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + + + TextareaInput.prototype.reset = function (typing) { + if (this.contextMenuPending || this.composing) { + return; + } + + var cm = this.cm; + + if (cm.somethingSelected()) { + this.prevInput = ""; + var content = cm.getSelection(); + this.textarea.value = content; + + if (cm.state.focused) { + selectInput(this.textarea); + } + + if (ie && ie_version >= 9) { + this.hasSelection = content; + } + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + + if (ie && ie_version >= 9) { + this.hasSelection = null; + } + } + }; + + TextareaInput.prototype.getField = function () { + return this.textarea; + }; + + TextareaInput.prototype.supportsTouch = function () { + return false; + }; + + TextareaInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { + this.textarea.focus(); + } catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + + } + }; + + TextareaInput.prototype.blur = function () { + this.textarea.blur(); + }; + + TextareaInput.prototype.resetPosition = function () { + this.wrapper.style.top = this.wrapper.style.left = 0; + }; + + TextareaInput.prototype.receivedFocus = function () { + this.slowPoll(); + }; // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + + + TextareaInput.prototype.slowPoll = function () { + var this$1 = this; + + if (this.pollingFast) { + return; + } + + this.polling.set(this.cm.options.pollInterval, function () { + this$1.poll(); + + if (this$1.cm.state.focused) { + this$1.slowPoll(); + } + }); + }; // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + + + TextareaInput.prototype.fastPoll = function () { + var missed = false, + input = this; + input.pollingFast = true; + + function p() { + var changed = input.poll(); + + if (!changed && !missed) { + missed = true; + input.polling.set(60, p); + } else { + input.pollingFast = false; + input.slowPoll(); + } + } + + input.polling.set(20, p); + }; // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + + + TextareaInput.prototype.poll = function () { + var this$1 = this; + var cm = this.cm, + input = this.textarea, + prevInput = this.prevInput; // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + + if (this.contextMenuPending || !cm.state.focused || hasSelection(input) && !prevInput && !this.composing || cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) { + return false; + } + + var text = input.value; // If nothing changed, bail. + + if (text == prevInput && !cm.somethingSelected()) { + return false; + } // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + + + if (ie && ie_version >= 9 && this.hasSelection === text || mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false; + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + + if (first == 0x200b && !prevInput) { + prevInput = "\u200B"; + } + + if (first == 0x21da) { + this.reset(); + return this.cm.execCommand("undo"); + } + } // Find the part of the input that is actually new + + + var same = 0, + l = Math.min(prevInput.length, text.length); + + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { + ++same; + } + + runInOp(cm, function () { + applyTextInput(cm, text.slice(same), prevInput.length - same, null, this$1.composing ? "*compose" : null); // Don't leave long text in the textarea, since it makes further polling slow + + if (text.length > 1000 || text.indexOf("\n") > -1) { + input.value = this$1.prevInput = ""; + } else { + this$1.prevInput = text; + } + + if (this$1.composing) { + this$1.composing.range.clear(); + this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), { + className: "CodeMirror-composing" + }); + } + }); + return true; + }; + + TextareaInput.prototype.ensurePolled = function () { + if (this.pollingFast && this.poll()) { + this.pollingFast = false; + } + }; + + TextareaInput.prototype.onKeyPress = function () { + if (ie && ie_version >= 9) { + this.hasSelection = null; + } + + this.fastPoll(); + }; + + TextareaInput.prototype.onContextMenu = function (e) { + var input = this, + cm = input.cm, + display = cm.display, + te = input.textarea; + + if (input.contextMenuPending) { + input.contextMenuPending(); + } + + var pos = posFromMouse(cm, e), + scrollPos = display.scroller.scrollTop; + + if (!pos || presto) { + return; + } // Opera is difficult. + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + + + var reset = cm.options.resetSelectionOnContextMenu; + + if (reset && cm.doc.sel.contains(pos) == -1) { + operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); + } + + var oldCSS = te.style.cssText, + oldWrapperCSS = input.wrapper.style.cssText; + var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); + input.wrapper.style.cssText = "position: static"; + te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + var oldScrollY; + + if (webkit) { + oldScrollY = window.scrollY; + } // Work around Chrome issue (#2712) + + + display.input.focus(); + + if (webkit) { + window.scrollTo(null, oldScrollY); + } + + display.input.reset(); // Adds "Select all" to context menu in FF + + if (!cm.somethingSelected()) { + te.value = input.prevInput = " "; + } + + input.contextMenuPending = rehide; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200B" + (selected ? te.value : ""); + te.value = "\u21DA"; // Used to catch context-menu undo + + te.value = extval; + input.prevInput = selected ? "" : "\u200B"; + te.selectionStart = 1; + te.selectionEnd = extval.length; // Re-set this, in case some other handler touched the + // selection in the meantime. + + display.selForContextMenu = cm.doc.sel; + } + } + + function rehide() { + if (input.contextMenuPending != rehide) { + return; + } + + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS; + te.style.cssText = oldCSS; + + if (ie && ie_version < 9) { + display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); + } // Try to detect the user choosing select-all + + + if (te.selectionStart != null) { + if (!ie || ie && ie_version < 9) { + prepareSelectAllHack(); + } + + var i = 0, + poll = function poll() { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && te.selectionEnd > 0 && input.prevInput == "\u200B") { + operation(cm, selectAll)(cm); + } else if (i++ < 10) { + display.detectingSelectAll = setTimeout(poll, 500); + } else { + display.selForContextMenu = null; + display.input.reset(); + } + }; + + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) { + prepareSelectAllHack(); + } + + if (captureRightClick) { + e_stop(e); + + var mouseup = function mouseup() { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }; + + TextareaInput.prototype.readOnlyChanged = function (val) { + if (!val) { + this.reset(); + } + + this.textarea.disabled = val == "nocursor"; + }; + + TextareaInput.prototype.setUneditable = function () {}; + + TextareaInput.prototype.needsContentAttribute = false; + + function fromTextArea(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + + if (!options.tabindex && textarea.tabIndex) { + options.tabindex = textarea.tabIndex; + } + + if (!options.placeholder && textarea.placeholder) { + options.placeholder = textarea.placeholder; + } // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + + + if (options.autofocus == null) { + var hasFocus = activeElt(); + options.autofocus = hasFocus == textarea || textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() { + textarea.value = cm.getValue(); + } + + var realSubmit; + + if (textarea.form) { + on(textarea.form, "submit", save); // Deplorable hack to make the submit method do the right thing. + + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form; + realSubmit = form.submit; + + try { + var wrappedSubmit = form.submit = function () { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch (e) {} + } + } + + options.finishInit = function (cm) { + cm.save = save; + + cm.getTextArea = function () { + return textarea; + }; + + cm.toTextArea = function () { + cm.toTextArea = isNaN; // Prevent this from being ran twice + + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + + if (textarea.form) { + off(textarea.form, "submit", save); + + if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") { + textarea.form.submit = realSubmit; + } + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function (node) { + return textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + return cm; + } + + function addLegacyProps(CodeMirror) { + CodeMirror.off = off; + CodeMirror.on = on; + CodeMirror.wheelEventPixels = wheelEventPixels; + CodeMirror.Doc = Doc; + CodeMirror.splitLines = splitLinesAuto; + CodeMirror.countColumn = countColumn; + CodeMirror.findColumn = findColumn; + CodeMirror.isWordChar = isWordCharBasic; + CodeMirror.Pass = Pass; + CodeMirror.signal = signal; + CodeMirror.Line = Line; + CodeMirror.changeEnd = changeEnd; + CodeMirror.scrollbarModel = scrollbarModel; + CodeMirror.Pos = Pos; + CodeMirror.cmpPos = cmp; + CodeMirror.modes = modes; + CodeMirror.mimeModes = mimeModes; + CodeMirror.resolveMode = resolveMode; + CodeMirror.getMode = getMode; + CodeMirror.modeExtensions = modeExtensions; + CodeMirror.extendMode = extendMode; + CodeMirror.copyState = copyState; + CodeMirror.startState = startState; + CodeMirror.innerMode = innerMode; + CodeMirror.commands = commands; + CodeMirror.keyMap = keyMap; + CodeMirror.keyName = keyName; + CodeMirror.isModifierKey = isModifierKey; + CodeMirror.lookupKey = lookupKey; + CodeMirror.normalizeKeyMap = normalizeKeyMap; + CodeMirror.StringStream = StringStream; + CodeMirror.SharedTextMarker = SharedTextMarker; + CodeMirror.TextMarker = TextMarker; + CodeMirror.LineWidget = LineWidget; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + CodeMirror.e_stop = e_stop; + CodeMirror.addClass = addClass; + CodeMirror.contains = contains; + CodeMirror.rmClass = rmClass; + CodeMirror.keyNames = keyNames; + } // EDITOR CONSTRUCTOR + + + defineOptions(CodeMirror); + addEditorMethods(CodeMirror); // Set up methods on CodeMirror's prototype to redirect to the editor's document. + + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + + for (var prop in Doc.prototype) { + if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) { + CodeMirror.prototype[prop] = function (method) { + return function () { + return method.apply(this.doc, arguments); + }; + }(Doc.prototype[prop]); + } + } + + eventMixin(Doc); + CodeMirror.inputStyles = { + "textarea": TextareaInput, + "contenteditable": ContentEditableInput + }; // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + + CodeMirror.defineMode = function (name + /*, mode, …*/ + ) { + if (!CodeMirror.defaults.mode && name != "null") { + CodeMirror.defaults.mode = name; + } + + defineMode.apply(this, arguments); + }; + + CodeMirror.defineMIME = defineMIME; // Minimal default mode. + + CodeMirror.defineMode("null", function () { + return { + token: function token(stream) { + return stream.skipToEnd(); + } + }; + }); + CodeMirror.defineMIME("text/plain", "null"); // EXTENSIONS + + CodeMirror.defineExtension = function (name, func) { + CodeMirror.prototype[name] = func; + }; + + CodeMirror.defineDocExtension = function (name, func) { + Doc.prototype[name] = func; + }; + + CodeMirror.fromTextArea = fromTextArea; + addLegacyProps(CodeMirror); + CodeMirror.version = "5.49.0"; + return CodeMirror; +}); + +/***/ }) + +}]); \ No newline at end of file diff --git a/supervisor/api/panel/chunk.066811ee56df2879fa62.js.gz b/supervisor/api/panel/chunk.066811ee56df2879fa62.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..1b93ee7b1a900553e88d4ae37550dc189bc41b04 GIT binary patch literal 104551 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%0Dwl+%tt*1KduxJL~t+HSw?7Tk`p-HO}o zxD9JvK<(--UZG_?TH4;XO+FH}aSOp+8{a!e^J~=~aCPfMXjBRykD8;~XX$oXw9V9Y z78`wG%Y6M}rc*`M-Q@l%oDdUttB(e5_Yl}bBV_Xs2Ln^1bAe;r=rNfw!sp6d6kB_?EDH&j{;lrVp7>I56pq@Vt`NRz%#lfF-rzE6|BPm{h+lP;ra z(wHQLJwpXLP@7Iyb)csFkfr>0GQrPM=lDsp&gH?w1S_R<^xFsN9ZKPt3=ij^?lk}SnYShH_WWzR`|Aw4vQPc;<#7hRU9HqNh z)C|IW&@Xgel$B=D*~iBe$3?Y8PwfT4Ba%$@pwi70H7!Rd-`DXkUUx26Vb~A0J4Y*z zUOoHj9R&z8YfIz}$%KR_uB5W=#o>#T>M%zK>ZuhhX~{{JJicS?3v`DE7r9f_nnr6~ zRaMysn%#P`ZWhIo1KV87QJo7SS~bo_3k;kIVMVu^#;w=u4H|PnWbbaE-atyHV-RYm z6!!7|-%Ko;&!eSE;v5ID^zTD8%OM#4a7l!-PVz%f_&?3C%&t zLgOKV7#jO7oH!i>CSD3E>(ijstp@d)EXog8tMF++PomWg99K?-oVEtulr^Wr4bedRxyM`Se8WpQ^*E_mk zuEH*Hl^=cB?41n3W+}Dl_OBE6j}HCr>OKe_$ABXf*`@ncUtA688tGXemtdRG`%#`} zqnHnBn&}}ARPQO+s++=-ip_2mkbks)(G4%c%e(uJx1X$@cD#@N@XwbQRMqkJFIN|@ zZRH1*+Th~#2bbFrCL!4OKU{@*U7{7jViOHsW@E?$@V10;J@{zt>b}@+o5up5kM&C_ zt&`0`YFfZxZH*Iv3oT>O?i`!qX6v5A5Mt`_MYD|QvX*oNL5Hx_l4F*tk8~VnF_3)X|9ZmFw)=08bY#!h=A$YeOftOt zjQYPr{tJ)K3A&GMOOQeb9{P>zP7R5;ADd9xg4ABXEzEmUaNMx_! zUHejcV8L)Ek(iu1P-S5Wbgf6fWCStbhj0*%2eC=n3BI6&jrG-HR%Cm-fPZ%O{i!18 z7T~?T#SEb5^B5C%I6&D~unzrQ_yv+v`)-GD|;k2WCEByC_hrC&nP z3L67*&E{$)Y|tYRRk*_$PmD7fumY{y9ZAZlUp^q23?yHW+U)p1Rly!y>|F{E=1WmR z`vg$HJovL7{uopL8-?{Rg|xB{X!cLkgu2V;5gVJ1ZszchRdOd>)Ix4Hr*aGT#i?56>gySImu9?}JC^aW22QSUz4`@tBsxqD4W_m)g{ZjD}31XnoeRa0DCa(d{Vq8a*U{*4V!l^E9vN1K(2{q7S z=u>8n=%QPzl`w+TI_b%av(>k_6Z2a=pD$NDl>BDUfSb7BYI!@8ViY=M~42|F{mxO;ZKYYj&BG#7=_rZv{2U4} zN^+K(tX|z?(XUrwm?$E<;O#MV zf=6|qnR*^g^?^XJqEWreubFIYYol;ROBmcef^9zMJ1lASb423?kh3Lk)sCTZv3uE1 zbb4LfNMgX{s)l5@t15T`LgX82N2Z*Vn958MEtWkwQbhl{!!g&>?2SITiIXwm_hmm3 zZpk;>q6?N2u>+vz#8_^*J+PHe`O1kNzlaE^K?S$3`}{2kzX&(gu{Va%!W+5UmDGf z>VsgZ3d9*uSLN>4O+nRZh5~8~HGGSqz^-uv`K2ihTL1(}&51lTK%Zm(sZ=RVid*EZsWGQU3)=_b5 z_yS6%wFl$%iYkRShIHH?3XJnJIm0ftJoyg>*>zQLQ=71_GnI361^d&sJ-j`TGeQ@N zlZ#c#QeB$rfu!xMay_mSExZr2@v@@M(g_P+%$L#@+(Kv0Gi$a)o><3`P0q*$hrxtlC69JU-ZXl*#CtAGjZTn7fvlxXEQ2w>A} zWG=-#CI4bcU^u=%<+K9UylNUP$*a-0P?7TfnC3G*!dLKX_3lz zgnjY9PCsDRu2sABRnPFCVcn)%+6z~!701br#@SJJ8X^jIC7$0zv<7;WWvz8Cm(5(g zTl-C6mJ3iz_P5=r@rtu_%&gA+ zsH=umPNN)B>gTg0Hs95N#fEq#TF0~T&Q9R?k0__e1S3}I7nj+d4V_)dAvyx?cN7D) zMKnWaqBoaue4kQ6r856ji+MyqOvGm@ed9(XNQkqXow!-*t22|diDt&{BujNevWbwb zw3kJdXkc=~IZha|wMn-g$(qX^KzS--aW??abXcks9}ls^A=0abp|R#Jo-JmGq;fS~ z=7pZe*&-+RL+(t&7v{gO7p_~`DD(%B!4+EHyG*+pJB(@KpE!CtzlNqB<0Qa(7s;&h zOjeyB;DC@h-*ZC6T6VfxWsd>FS#_C6&=M!imM?}sV>7C&3WC)|cl{qm0BW&qQ!CUg zH1U5Y-F2-D84Ngj!tL4>74%6FU)-iI?FH{XU^x%x3vp!jO}GKiYsqhH=a`{^yFkUI zIs|ckZZ${KMphXoSj*;in<-gLsSA@yt_z;Elv!6nTEEaQ{S0%eC^AfLXxQh(zPZzA zn&q%Ms^smh$}x$)yAa`)Crr#Y1Wd#Z^k?zk%Lw>;toZHopI|N35hD09m$McK7h0bC z<_;%+fI}kTVs|&%y|jt52RM2XC)IF>c{X+>Qd3r|P5f zt%Qh`G$aap?u^C#`c5a&Qje>?#}qx zr#d5_W^tmg4h6zcf=nov1ou!&4V9ATV@jlp2`s;P76nvo%`YRx)tE~U4+WDuHgTJI z_V&ayP1Y8hz_a+RPIAO7=I$_avmwOZr z<|bw(pS=V)&n-LvF_ z7=D@&EdkBuF<9&9_fIB}kb>pcT#oh$Pn)jG@Og&vpeA$%+u zlY~TIjiVf04uze?G_LEYESw2akILk$um>m%o>R*ho#ecLTXxp50<{J7fr}0sZNhnN zC&6J=$pV3kyNqJv=%d0})TUW_e0K8v_h&>V(I>>lpR+mT{Ug3@=>p;BctU?a|LRNp z{d%{DpUG$R_lsSA`C>x#pYDD}FZA;@zeMJRYd&MJ&&I>g>96LOuP38XxQIslGX64} zTn-+DHF?R!w^1ICC_VSU)@c9VY-OX$-n#NsdEwiycKKu=759tmkJyDkpZtK9DT>Q} z%5H5L+O_mw&>M|v;Ew>h${f3NmSJv@@Llg%eP~V7ex5DnBVC!Z!dow(PWJZD!3~In zn49mcD*+Rb{%!2u>2y{su>!13y6L;F71O{T!Xy`3pAAg((iToS8}X-njUA%4MH=&= zLdm-4eRZtJeZ@NGZ&om*JuUEnQ#&>UNtY^>(A0(DlOP4#?pSg9C1;fY!Q$VDI;I1P zf!Hed|I7utNNr>P#wpG=0yHR-RYKVas8Tqy1g07dIt(D2#;m~A>0O~qunz|YFQHXY zwqH3I2tF%>uKamtA@-d&f` zp3w;Nsr~xH-S_jy?tOAVCngYtKoCVEYG~U#ob{OeLs;u`yiYL*qh(|x^I2yyWgYzF zP8e9QVt=;eMt-s^M!mATJk7|)%eVzQ4*VH8&z_RZZc6#dUt=tncQL;F9H|+ZxEPVK z8tFKVoab~m5;AXDl97Q&)?}p07MSHoa&5eFCnE)qJYC+v{QP;ska^3JFtFpmW#q`3 zWOqzh;yYhcieob} z@Mq-6TCvF%nC05|$sO2mgiG%3Qx^Phq6U97Y&5Fv}j8j;T9ybzL7}qh33_Q=X-IUwpcZ|Hh5BH5n9yjIl=f0mQUwWR)7mj3)pAp8K z_-^`Z?K7nZZangHOwZwg4VR3HP3|JEo5Fz^&B&3ZGis83+wH3XU`+lN~ifWyo;{F@n)A9GHKf0tw)-9H>qkk#* zDUrMx(GqJ!#$okn`MLbL<7R6JIdF*N5G=qP54N=Nnw7QXyQV6S3|}J-zRmQa;3lFa%1`~i<}rB&GMPnf;TQzu49>Xu;PwM`|ITpx&hB119QZE2;wC-1d5-~RtNoie z;>e)?k~OO*Z{{g=JNfgUWb^1U~tK&p_z+7ti&OpbzuvM z;Vsg>hW@>(P>tn$7)vQ#a^qApbeg}6a@)++j;Lx7;7_AAiz{j0cL|9D?1C^3HxY8b zM8pjxbcnR+Xk{mc=Zbc1^mR)}Q{idcPjCt@vQUZNXN7~$x5?HUZsBo&6xPv3aDZy5 z&sc#d^UFQR`%gaPKq4*tHv#+yUhh8o`0->@Dui8{HcAu#>|s7=;R8pD2EQ|~5!$7m zVtwN2nD$W08Eq8o_;M>x{8%f636TY#V85$t;q%2PYB^nETp7NWW;rdf@!--?|K^QJP}MxGfLk; z!<43On0$OVVU~f?cQUZtc?JM1uR;!#sar(d6R6Z#bac6^17DN)_9edk!qD|7GFD^} z)CC(7Wo@NzK^Z@e??bBQN@shIi7g|zY>(0%aOLCN95Z>W^i8keCWb?9Ua72j=1g8P z*%BF4wM{Z-wB7q)UA|M=8$tCmcx;{iLh0WKO)X_m||Fy*Od62-||NpCui$G>&;#2V}30Nv;2KI$d7B z%lgH>=fpK*QJi%z>^LdbQeBoco6XFZHhm42CF3&uVEG(+P&EEvX_I=^4}KU!n(^;o z_%ZQPeL`;h-Ypf8rQutiQhk=N0-zqZiX~9W|7u!%#dY%-V}V85UnI9Y$N79BnQCNH33QQd1!XJ=dLam6 zd#{9MqW8 z5Qn>Fg~mHe>_mFeR_B{5|0+xz?dIBq0e82rDlB309~s%jNWA8z*tDM~+ClH1y` zB(Ej6yN_DqDYBAMTE!|(WziI8+WXt9*$dk%*?90|AOjhhU{Urvd*0pcbH-vJfj}S- z2m}Iwi1X9%9bdbg8xA~Y^VK+rZhs7>hn1@F6z~W33l+D}E-8o7DRBC13bAwAI--`u zKFt+>x#1Iswu;OnHT~it=A_sspPTj8+CgHRPTxAXKXcw<0ME(Qw{8YI=|b>oJ2NL~ z3RUBt(0?)j2y-AXP3e50G6lFmT5goCVpz+~GucnF;k}6Vl z(S4XxxjA1=VTB`R%F%A#1q&+v4S@A43g^`EZzhk_-E)vx? zJgA6(a3o8*tHn|5H=dBcy-RNb)* zD;^V^XnE32jb`8W&gnhQDNn`8l-{#bdarLv!4PqZ?zu^24NU7@tbg_)zcy}?6+%#Q z`Xkh;T&DCO>`4lTW8f#^;<54ldknty;aGb(>Gxte6bmhGPlVz$DxPORy))Be5xb_ule@V;6;9;HzhsPEXTLPiYtUHcrsM24)K6 zac!o5R_u*P7^z5H(jDaUFuM}jsHC`QCx07H((p?DQI4G}nCoMO?z*qd^kTU?ZnJ{n z4>O)xFDkf`MSfz;A=|S`qc!VC5PID0WuM=3tHmEibo{=TPd+nz@_WZ8tijpy)Mp#a z{)^1)v;Ds&?TG*%BK(Bssdr+}aV-3bLBM?!l{uQ0J*DVv0~|w?pY+^Idl7@uQf7~^ z+Q#^?r@Vaw+?MMC{P-~ZcORqm*rKN&*~fwWaUZ~d)Q|l#?ni;Dm<@$kN{_Xzjxar$H9*S)A{0VS0Jq#yA~cOF(!gh>q*j<{I$Hh#0)?I<{UD8 zcopjLZ@gVw%OL^xvo&52>MmvA#2#ktbU`#x<%tq+ejGgB2>r6Sz!Su8i^|AG$THmt zD;U8}md(gkab&{4(2)1mCwoCV-V^P(7=zg&9CVI_(5X{O9oX||&z*0hb}d7sIkGCP z+5Gm)!SF7^L7IC!k>L2k{1cMB?ah*MZ}U4a=%@B%;lnsz{kfKTa*+K z$}(WQtPZ0jQmClma9Cmwz!v6!Oje4CR0d+C8K@yY2V^skIT4p3`AjAtz>I|c3ajEm zRxNgU6U;lUYnrEJB?V_us0t+w z-K%8?GElaQTU#LTkSLk=CVagg?@aihks2y4?QyR!tHS^&Kf<5B+M2auUrbJAvL2^oYR!kx0O%PHlHiZAGcL|7d+p1R$;c#JeM|Zxe-&ZGFw=(ZcZM!%+A0{8K!{|zL1+IeXZym0twTRw5hwKhA zgk}WOE))@CKL^%4oJ<3qTOKw&HA(gn0GTB=SOGJa7k{ClGh84<|A2VI|E~H;5DPhP z#?bqYLq5<-0>J6DF7H_xOaQG=R~_dzW%G(6xyB79Uwe&95K4{s*mkX_a&9!%TP9q~ zj?tB~+^4${s?0caz%Xp--t+r5_+c-B$KeYUciU^<ti25&iB{%PTYinp(`qXKr(sJ;{mk^+Ox}b)1-4(K@0ImD8>%sGpiRjm zKK5N~xZMhKg|-H&|2Q5YlKicRrGKv%BTb(D78+*+@`Dlw28OXOMZAr;;Mn>NdVvNy zw!fvlA?sv@7esS;@$bSxTAtPFDVWi9t7o05T`Y95u!5T<8SEfyu>RCswiFUGju6nGOw zq6o({P2CXpPm1;xB3KfP)P@xt#ZStU`T26YClF2DipM>L3pws4Tsr20IhIpuIaPEi zOwzEWWpBVz6n8Fs_XSWaNHH`KHS7lyP0w7pFZk&jRxG1Ct>@{4Z#XavD2^tWfoBv3 zVW6FeoTd| zE*WWjQ=f@8dY<}Oc>p*4s+c!ne{^>%%Rm+td-bCh(E>3nXn zai0d!ImY$Q@{98$39U)FmqEu#FQ*GSS!z7Kdp_=W31TSHM~k*YKTjNCFVXtIG0I!d z2>5|gx!xSd_?RAqL~`DmNuez~#77UVx<wlK7 z|NCzJdxNhJiOKYVx+rdZ^V7= zZkjZG18~z~D1`jz<7o1Bl0JGP9GeJW#<*Tz(Yzo+iW-3Z*mvX$KW+9JzA zmKQUO_XsY;_ntl)f&1beA<|San7jaoy;bDe4A0q`oA1YgIzVS^o83*C@#-tzEX7*! zO^&G>_}L0dGguq3R^`vY1v&A9>D6Gqo8+O&ig8|!=XF^Z-B z7C#n#jj~7Q@PL*@wED;DsOeX1*sI&BUW1W7D;}CngGa?|@UTr;i;~c}>s$IrdoGsP zVbPJDt7TuHzg2Ibzok2rnC98=ejraLi1=95{O(@_BA}Zx#d)sVQ3uyhd|%9?@=%af*iWv%LJw} z3nLS4{;_)aPhlkuajM3px{Z!`*rce!(vGDGw=pD}jS6j}Nu|NANzrW@;Mzr;&#iSG zr|aHi1rfuY4}Tv&6#)T>Us`USsHBYObTfQ7%X`CR3Djey!j#78H#Xl zP!mu>pKrozs_`h$@AXf1tgU+U`My(ku7D;y5MD^ot`@hyA!WR_K+%f&OtF>|)FKgtt-n81m zfDW{~CJ0pzqmS)3r+A+e0A0Ps;?^`UV%%xbZl@iZ<8kEU3;X#|JtivLX7}2jLII-P zwK0YNZG}+3r{UTP5r1I_h4}`5BO`R&vQUK=FuJ3hR;T6jSbER|l-tY;wH?#$Am`Ke z@n`^Zvxa+5iFn}075e2<&x$vda8E<`cv|{yek|{kPfIvQR`qEuBK<=d5^(^|>_=Lb zWD7l&Jr{Osnu1Y7dMrYvVk`%6$wmq!A|&0~n>4MrnE|x`hrRvB|rX~LzYVl##yd^Zo=g?#yGzB4O~OYYmDKBML7p)o74n_9d5n+i3BFP&P0x4 zYbD3YCXS{PA(1dz`m?PWJPO{rn=q6Dtm$!vQSIKXwlIC$5FQBvteM_%v1iurzY-|) zV`9?>qab3PB+dsyg~i5~5$a zyfY6(Yh*(zZb%-#yiKCXCXF}6nOhmEhiNrOU)TKzXZhP=eyGxEi#r%NUwTuB9mGwi zs2d_<)%d>aT9@7--qXf@R6b2eXc=MYz){$r^CJ-eND5Z1(hIxX)Ej7MiNTZ5ejY^A zmzn6R>IX@u=d`YV$Q2ozu&=WUM@BKYhXCTML6+BZr+vkNb9R_vO?^6{QiRN3Sw93c4N%_`Lo@JSyi ztxu>!8unyU{8v3!aO3O}y(nl_?K`5f%0b`0LbpJoSBzya+*$BRw-PX7wUWbkY(Pe3 z8@};|@uO0=d6w{V(9^;0={`e%GjzVwubz-|b*9j&BwK?xmktkau+*5~y; zF8q%xsn&`wCW?{&mh)3<_ORuRSQAP^a$YxiT)tr+X(2Cu)82sNs~#*O?r6~dh}NKF=;k+4<-H^I< z%lf!wXKZfKNph-_`H_%4*Ok$#*B=htQ6<3ZKdY=ka()c8+`+_DqPsn6h2xawTyIlG z?6UxW`(xAk1AFD$3B{b%OeEgjN%lQNeV%T*xV5)*lRzl|HSMDP*RK=;I@kdz1br(9 z&9Z<<8@2p#up^psmW>(fNb4LYOe~ezUrXm-I6lN74kqf}0Y-4U%M}MZ0c_^dSW*Z( zy^=yG&PV~n|7>IZe=V8>dEiapJMtjjkbjqYbgUdP_QW83<=~mQDBl%7|q{t!b?WN14fXYx=6skK|itxwA0Jx~Zb9n{%SU6FD{scg8GenoRtYRuIZ$ zUhQ$6=CyC9S8ox?BuDRmEU|U_JMW#NNaGAE?&&z?6Srn=#`@&pj-L~g!kfr?7&$6f z8n83>h|axzL$zJEbj^dES%scNPJ*d6l|{O_Uu&jTS1%;T!^z} zyjjMP7?)D4o3_vJj@c{?xacvR>f9+EplR+5?KUk0!MyOL~pU;Y}- zFbNjF6bS=&+?m2~u2j1MpwR|qb72Mp_qzKQl0i4Ty&6t8V{xIH7Lj%<%!3rsJ&oS<)zJ9QS09*$ zKh*|rgfAd%G|Tx%1ukMBK~_uf4*?uEH{8f-m^??W{|j~Sbrx!39~!I3F|?72iHIaz zZOZ{UD~TDU(q7=?Or~bInl{qDial$>1MM>@Xm;*I*oZqzFwK50QJKvIy z84cTSqU!Xj4*h2X-4%K@n+EmBv36DP&7`UA-%h5U#kOuo-&ulYUam!gNrn7{j}k&E z_Fkt6Pgi}(U|UUe**WA$x^JV9ikd7X_f5gAsEc~I7ztBTe7WAV{tZ>93+ng!eP&x> znE)?9(7#|$tfZgjJNx}QR+>!O2cHEDJ$f&R_Z6a+)Auhf$`G=OtBz_!ve*EC8<0z= z!%2vlW;E8@q^V>aM)lGzoFB|JDS$hNAE@m8y_yL$hc(^D+R|pBnUaVR|A_Q?Oh4a_ zE~<#!iO~R2MqHlB-4FO)T!^GE8P zJ^}p4eq>Ci%vW|KMyGiXfNHfPfO)ZRp8Y*v*D+c-{3kX@;`8X6XLxmVR&$%;44Dg0 zTyJu|>95+jZY(baL{)FOUeaBvGnatwkFtt#Ou`jqhRMFQn)Zs4@Uo(ZvOl0JkOna-6RPS44ZE)-*b+L=Gw@O zlUxzJP)MOU{_H(#Wx^hyP29YzTep$}S5QDx24oBQ;3v?Wq@v5f{HJp9SoE0mx;H7O z@5i)=cCf_mr=A@6*KPpT92fsipK17hwTL4DNY3B2dzbcV8Om=|5CUKKp$aCmt_INn z*S^B=-*}~SHx5(Bb3HR95sd?x=`urs8b!d)$pK8?bjUUWYn&e(dl(w`s*hVpDnFLI zv2!(ioon=v4pDOlMt37^+P!fT@D^|Mj7%T~rV6d|_bhOm&Em=qLVS6&c5cj!L4*IQ zqx`Ii`Z~TnF8=xN6NH6XihV``8im)os%DEEN5iX!wpXl(c5YhWy8(ttX2lunZ{0G} z;aMWN9&w-d_8RgzG+-zS(j)1e>lwvd&x!VmVylr_;nS;`S}9@N8y9Q(nl?RAI84}~ zmc`|l73;fq(tuZJnOQ;ggeHJ#mx{_Vl()A_#Y59MMMA_Nia^|gnqLWX_D-!p#Ta|U zysr<~1RF-DI{P`i73IU_vTUr5V>KS5I^U2(PgB>(cL=x^3=CB1_V&V#SFOb0S1rN^ zmLX~{A2^-OD<-}W%dF86)n}5utEqF+K9h=`!tdq4y2PQCM=Q#2hPfgHOkS!v#x@kX z$EV6b$E4E~SRa?c$;0M2CNgS)oiF8eb4^0jBty)9UEw;tI=O7jFbV-gy4^^KCb}12 zSTklZSO)Ye=k;Ymw8_k{5cG-TQ?fzelE0KIbDGCU9*eG5^G#Yhn;;STvPNVKso4|G zSMUT?f@ly)=}Z~Yk|=Vy%-oc4ykjv9#-@rcqp3wSA^3q`F6@&-4&(Xud{rnNr%1MO zUT-a<&Wv8YPUDT>_t@m@QsBw%Ps^KvXnKUe2Da>SljLO&f`+&%4*ZGSQ8;gOH=2$wlpgQUccWx{5mGL&dvlqTMy4q1 zlCJgkS~or&Mz6HG1~uiYxLfl(tY}eR>f4-%vh6Vj1G#GJPrZs-JUQ-u?rdv0n>b*z z-Xo^Fh>f8uj&GO_w5^?z!v^o>cZwUoG;9^|vk;6Pkk;;r8)h5r0&&=lDrGmAtW|@E zwAYWek9HzW+t!NL^LZ+(atLznj?I#|cNKX~UWL?Z$5oxYxSgWau_=tjT6RuyZoZSLZn)@C;?BX>XI9*p)u9ioz@*8WDuOfnQuGl| z*@_VKJ(d0>n>EPL?AXpBS_gMy<7f=WnJ<>})rT;!{>{xB&TgNMv$?BdtChk)FAMVw3d^1>F2Q@B1NZv(3lNfjG9;h{ZA*&6od-1D{$PZA4@@=s^ zh(SSBcYoZZ^NQ+f)rGP#ZX)r6okz+te&*%Fe*rMYX-fSSp96;@!8%e%RO?~BzEd1YLd70`K?P;tbIDdZU4qcogi^Wc+5v7zR{8I0#^1GfEf0G@WaiwFL`|{{R zwJqwhJcXYig5k(LFaMG~kWYd5oTFGuu48U(CYZs;ExpPy8# z`LQ4YwVT0ALj+rt6J`q`UT@EXA`oa8z}7QoKI+bZl=jn~w8v*lb~mGjddB;|R`-99 zgZS~%84j@qUv68o;`N46vuI9Xh&wiKuBuz(7LupvZ8QRLS?F`N4|maQf;8@|jk8%j zMI$A!qR6)K3cfxSNsC|^=AF4-}Hz+v&p4T!_u9PZ#MtC?{7~ht$YBGFRG-MJ_fm zWQ|hQv_6cjGY2V!=1xWUjsT`gpVa%=kG_z z2=0Kt9|I65v8b5bNKoE~7}8a6{Q1mCaa5Bsc6K+oehSEWV7Pm*W!G!z z=EAgLqLjP1V@FzqqJEEbGR1K;c3UPPhG7j{;p3*as{*&@z=q>f{JC-OYiZcyM}f^hjLDB#qC+cFitHBx!=&JV_^=PPiyGL5r8LLi zj48pmw(;1?-u!dm7HvF-3XrC(Y@Gr4fdxaBXjJKcXT~K<)DBtCIQ*C%B5{;Def~88 zKrX*15A7jHy%Gd8jU>~@MIca&hz1;1Ya%Dr)IAXK;l~#xFR2)*oj_`HF$H}FzWgMT zi{1@H40n*mp|VvzxPe}qv?LuVTHGLYE!D=GkbZH)1d9_I__RURShuk`3zd*Cwf8wq z%BkB75f#!AqJ*=nYs(isbVV^xCqTW$B`E(Q+L2>oa^HVu}r&Pih#{^_nY*{Vch2;58C$NmU)FzKFF+* z>6tnPTukgzeDua|nw{#YLKRW;%cZIY|c)rHyZrFwp`ONFbKI%>J#8M?&n z^c{HD#0GJ#hXriatuY&lN`1UMuZ7ZIW2HVcmG2+wc#C~otfgJ6t?d;(*lx8Ac5`;j z+Z$Msj%2S!*@#=ck`^FtSPrd1G0>cNPe>edps_@{Y}eV*ejBdaAI7>5++a~?hT3*F zUR?kr{;?tfRyn_gwN#iI93K*~*wbXPn^hGo#E%8~40PnoDQHI93==I&hVLO*lMh+#L5jYB=K zuS>juRgOZp)|rK;hiDwBR-iA)?b-o%-yLYfqHZo}4H z<}ew@@%vVGa;+a4RP5I%hYrKDaRbC4-#mXeQIE``DQ<@M^0?}|nX+e#hC%ldz*2XRqkUN(0 z!MfeIIKbr69gY1%5$#f`!#Q?$(Mra__Qb7s8;M_TH8Yld)!@@BFX#R9!)>fuksHS{ z9}xUl4JeiV$mJCSiDLfZDDt6o0>FGg9gI7)K~==j@pFj^81;?5*=#@GI&@U|xepXa zn`aGRDaOlOjMa?ME#!M#$oRtxWGOYxEdAfer?*b{8fIy+0>{{&8C~3f=DKSx zP}s$l+~vj8XB-{=xDP^cP@frW%_I_~h^cb}@O2$qm?srFC#eC^Dju+Gm*BCW_|hWy zKDe!u|GpP%c;G>*vb;f(RZBy5s-8NIwFcJRZGd^>s+F*mA|^(K1m`ooN1(RCJ9@P)2Zw~3&5revha z;53SZ7>Kbc;swE^NoMUtiD`(xoe)9UZaa_FV-=s>&M7#8hF-NYCTX8@8(nwz<^R|) z7lMcVW|rP5Xw6#P*mW_~~sK7prYi`hLnp6;68C^dha7Tu7F3(AnRD`L^981(3fD)H$Iguoi) zZwTeAS&7HhP$eCLVo3I~Uv%Dyn8k^|n6dFUsaHnEs2QMTv`< zR%fWKFyziPa36Hg-8M2#2G`y)>r@`j7Nx&GQrHeN-3FX7d%o=(?6gqy{|5&|RCXUw zy2pMM@{lo(3U^c5G_j%5I>|@yXJ;rm)@$?DkVpTTT9aBY=Nq`=t-&7Niyv#d*(o}4 z`udH_bg#NI@FoE3F$>OHAloXhCscmi?`Z#(D&~43gMqHS4S2UZ%5kDO9LnjgZ1o#IjrDMZhu^D>u{CMU;ywO#Es5`X&ppir9dK(SLdzf zfz1`Q=L{F;MAqs=^kVGUk!0WM1)v6>`R#A-w#R+z^_KIBj!nVS*XPmy5vIJ+!fOp)JlJxrFndjPxni|Yj~t?cD~6Qo1G z-Zx)a_nP_SyMS6O{jqUK$4v%KY7*`J{!c*CjN!qr(sgSKyU(uuCns=RZnwOn<|72} zKw5U*?ANN&%x_TK0OOhhUd5o!<(Q}iDy(v zS+QKdtBwhrY2u?_L)4lH#2_(a(s}T^6;pJ6uoYu=Zi1krtqw!eE{)G?MlR9whLw0@ayO*oJMwbBXCH$T`?%?L zh;CE1|38>~1+CDu)ABE4r6tTELf5@%sbYSGlTTbWY;RW2APHZr&2GHYmTeB20!FHI z7McsFeTXW~Mnhn|bRk-3b8YG%j*}%3A3%{lY2H3V5w{FIQOtN=Gy%PE2gZ<5`Jr8h zqGr9@7zoemud2nOT(xcTeg0323k^T04{3h3(Qxevn-cwf7|g5y8EP81in$ikLSqtE zY)s}o$Ngzw;1$e3Bs7Fe07WP<^NG6n(egu~6bUmGxwG24s21woB+ z{>wF4f^a9XT{M-UBOXcog5jk;4F_sv5v0H1u#@!+4@PyyXh{A$a-z5 z3v}usovywlarj`rnxAp%eS7f9o$_seE{i@99#(ndaC~f04$V>3fY0*y?$@+v?W!8y z&lwhO^l>8x=5F&dCWafvoqNKH{Vd5QLlm9t&as)S&+a+9P2M;^5{Z}J1b<-FN87lW zzdVZ9r_E2d;iJ$T;osXZCNb%ow$`+Q{Z})eo@>p`I%~v!2NSC~Z!z%(O|!IV#a{kB zQ!I2~#o0j|^V!sWpIn))?<|w5&xMmVwfme4L!AbJYzQSs1=0bXC>eILbTNrnClKh6v=H&%NK z*OMo74c6RJ9_90>VQkOmADhS-NtD1Oh;c4L#vX1%7ZRm3Z)liQrvx3zH<&v8d&$)i>JktN3S0huU>!q-Q(Ba zefv~C;X|9yx7PQk;)L47TajsA&bM@kQ`y8DW)V*W5MTCFV4bXy?x#%Bl}y@)`rX7q z_}xV4N^~$`pXyY4W(L^gg}cdz&Ea~t2-Hge+Q679yKEo4r%ww46g&zx3Acc*NxH*R zo=b$}&VdBgf+YLUSH;qx>HE~?r`?LBVCtMAU7c{$19O|s_bX`RB5V!DmoT{jDhCJLs0 z5?WNyXad||;Xw6Glu%ereDxmQ{Dqe;8NZ1q|_K^4Uq` z)7x?hGde!q`|bZ_Wbz$<%UEn+%qK6OxA~6e>J6_+juT;tnL9d{BSEcU;^o^-d=y4L zyQ%TOVxl31&(Lhts$*B`f>j<@C)KgO1mzny^h|Y|X~Lp;pE2L)%C#tY;f(FJ4s$J-X+7#k8pU)z|ZWxAIh3Vz#f#v@o8M)o0zAV(A=R&6r2{bF|a z?Bl4(jbKDKsKpJUP5n^rH}K_80sp4y_O0;nW1;u+3X#V5Fs7K7QBm91Kicx;ezX=K zrib};d@9vjC-cp`LQGhZoyX;V8uJLAyW8-gMib=ud>K~tcmy=Q-_W&iG@%UO@N~{+ z4Kdp^ZqK%52woVUllu!VrdB>bBeU8o&q2e6b*E!);!3^ z9D#cbC`pDUOSiFOrr`fYIbYIxeRV{<MYQ2SE8-&2bTGH|(Zn_l@FUm_ z7MiBXFpxL~o4{){az6YSbg)Tf5aMT#QU=h}H}+^LQ<#i^^DQH8LSw5S(8F$r4T5_u z(_yxoC$}vfnc*t)#69t*u~l&I3_Hr57TZSf;(0@Ob1$W1JU0ElT5R7x<$mVZm5oEs zplKm+7u{XYs4G(8(M=tLuxSph>`aDKbw=PNGS`qD*uik!2 zMAMXDoc}m#lxEap$})y)7SuzLq*mNqzABe8tLqSg)R&G&GXfiVi5f96z!CVF4fZZ% zQ{KatG3qt2*VQ|beL-4{xQB=ggSvr|bf;@~vQ6T9V2aJ~h~^G5ptpH`^*hIN*7ZI= z;_@;V$EsIQtmjLpao^xD@P3Wz@`ao{}%AgU&j#pb0tW65JmGVgSIw86&Dv~p&GSSv^w*P z#;{n=s=hFes6mjxl>i2COea~l3|5;O%J08-$>b!Q?0s@RkM_+%NvjF*tIh zx2axHcB6FrOlHVWnx9{8=I_F8>vQBWW0{Rp4~#6bIvtS3&+wSoMlx4ectxre%a7$T z=Pj*Mf2c$g2zN#ZzuzQ3*$a5=+d;Cd>#Wb#{=xM2?;h@&Y4u0I(xg%Aj$6a z8!Iy32xhYD`mi-Sz>%iIIgoc{Rx`wDVIlgJr1g9a0`fI{R^`)OQ|6=q>A}^RQC!jK z=`ro*G^9eq4znHgFatw=Tgl{elcZ5#&?cy)(ny={CFJ>6EjQFrB(LOx8X{Eoys>sO z;TB32#zE|Cgq!uU#GY$+ve8wo03OQ;4MC;Mv@25XUOpxDW(1w1{k$eWd%y3~FLoX-;pc{X*NxMSqMvo@e!a=|w>x_OhsYXq{0pRw3n-K&qOZ2Q zP-1|MZkMLQty{hNd9Q9#99m7s>YC|(ayPsJ{Oq35Gt{0RH8B374#vNApO(L&k)>xK z#2ZXKpufw!xJ(uSIB)YyeqSS|?M1LBbHto=C z&oQ_AXq55ZGf4Fqv5&*HuChVoLY1;PzBAXH491{^pEMX5_?jVlo5~ugcPmO5YnDLo z*z7(&x-)X?lcU2Dj*dhfxV>|8kn1Vs&rbb8WaW*{iYx2sY9c3MoE@~t{F=dJf z`93(ATg%=BO3>vETLV+?{L+o4bYbCKQ`IA0gy8-C9U9u$Tnkhy@#>x7PP^uHQ@is= zlnAVgXA#Gn-L5;P1HGA`zBKXoZ3OC-e3Ec9jZbqIX24le`tbt#cdK$yZEUCbU7GP9bXIx$(scCFXaUGHk^x!8L7&|8a(#QI;S+sxG$jMgtL zABidoc3eKsS4DU3o;_+I9=*DPA1q=I6;oe~ei4BqvV z>42LOYoIqob?Z5@TE_LJV(&ptT%7;7S_#{N3d5gTfkzdsljzlWoYy8c`bw%(9ZsNP z{y4U@=&6eSv?Aqi+KbA?SY%{3C)V%Vm}!equxxg=b>36!?PAOXP;MRW0>C28pNcID zKnyChJy_~y;>YB^BxHQH5>Ic*EPvpmKzz}plHe6!YWdP_wazFUHq0T{m=AO4;#!~{ zA{}-OZ8Q=OhOz8VfMFj;ffun?4L;^8I-_oaR!)XOhig<9g3g9@K?Rru(kES79iKh2 zF1{u^HKDiJh6M`4%v%>+>_58ZMaIF2G6HpZ%t9%;?0A%vgFjv_zzdzriHl3lqdHLye za~<#U2h3ca(JhSRj)5nu0Pz7ae%LX*ppa9X`jcFJN{Ss!o$asHO7_hOqI*W*5EV`w zXDT)T)yfIzAl?R)Wt=ejLyXjEY~Czn=#dfv$Px(49f$b-*^2ZxH7p&x7RcrnyZmuf z42)Km)C8G3o}xwX(R3hu03S%wtCPuy&zUcvb>-4{MAZ>ky*ZODFBxuZ5);a6a2}KW z^HK4&dOe@cFPU$?K3lHNS5o|)8?Vpo zHDTJk9dBAL(tzi4wC?q5TT7jbRjo)ktXPjVYsoLXJ~I=vD8-m6dD=y&AvQO@zg4kg z-ez_l%x}urKw{XuJgdj=(3x4V_+BgY;#g}p2^BZ>dh&Z%f&jiQ}TW&LL0gxiWLxh9zVv^tCUQ+lo#*f z6h@sr1x`NVKv>h~zK{t{N%mDkF$+i)8($k#DUoM?2#zAx-Hiw9zZvM`)-6MzX=s1C zTN)HazHdT$A}hm?mo6+OEKI_^za#%A>%*F^!}qL*@OE>lpEFF~GyzibJ+>GS5Bx}M zQviu**__F;c+z2Og%NHWPPWi+FT|B$&Igb5%;&>?Cg|p4QusPBtJ!>$CjCB@ePfAT zfj$=(ayiZz#mxK!z^JS%R65}%j48rBhz;d(TFUOfs5R^;?qt>*ebmZmFh`;HIW8_l zKd7sE8(*?A(gSYWt5eDH5yBpqAJ1fi!q&|$bYytj35lQ~lR56M1;B<+qmvlU95sNb zoS{E^jhEHuqJKqy_S5D8C>(Rop}J_iJHF$H(}}qgATm1UDJOvTGXlI~S(H;km>2Sp zzQo&D@KBuuHL%E!#m=bf=V z_+7!i1D}Phz6~=$WtWRvql5|#?wJ6IOPNphnc3Y~&FxZ7fZL6Z;CdH?2kWXiXgjq? zUI^BrwQ~l?n8BB}g_sju7Cvy{nT^PS-{UGpmV3Gn+L3A;*m9Wnh9VWS)9yUlbH?q5 zGw*|SDNdO^J{{;d35>(CJi+rqY#3*S-ix<>6vB+V!6T5yEyTlx8*2ObUb83H(-@Q? ztWnXK7x6tye7V%rWef(!ui)Eq#GxsFf=IL{C&nuw40%lh_~*wmd-}TF2QQJm<1zb4 zUbr`Bo+-SM$k+WUg~zm4vp^$W6uAag!NAgr_esJ1*6^W08VBC=L4Nv}F9r1O9CBy? z)L+8K%-A!KowK6_tnb5iMw8cL1JLMfkwWVtXx6=>vdy5RL5>;+Cz3~F71ZkYQ8R1^ z7Rft$sA05>Q=oi`{pn(Z-EYBd?ERdf0~r`T!i?M*zr;+xc zqGip&)NoX4FzeK#JFWED33V`%Ls*6G_ZiwrcFK`|-W=gGW{bPU9IB)7JLu+-pfpVz zc?~|Pow$p18|Ggz{mCP$KpA7?zx0LBy-aelw53ym4X=I?S;hy=&@Bcnh(4#R7^2gKp+&HH zH>*AhxUHBHr*XA)v0a*D!37czZ_4wUA}sEm8e66q3b{bVTI2{UoSm%}DzWKma7ECt zmWk_Ncv(KlB1aQ&dnyCdpnDm39X{}3P5@tjb>a%+3y8QKe9b&KWD~Xs=3k?=(9T{w zlSX);Yus>YKucX<=3+V15n z*X)z;%oEd->SMVe69}_n##!`DcpkqO3JB-*dOKh8EipLw?BhXkfnS8#Taoof*HeTt z6XsO0OdG!oa4vm@_Fk%Ka{oB@mT0KQ`%J7bh2(hv4o6uoF!k9j<1_f>u@f^i=hD%y zJK5Kq#C9C91xaD&%~tah#b&!MxWbUmNI@Kr@@pbJuV!c2<+sAO|b%ZOoMA&roy+gOUyoocTf1tn{H%%zRJV`qt zrsjIe^g*WhZo59-%;jNie-v1KUzSz$u6f#XI%s#Qb~t5S`=Io52aY>(?S7OZw4KjW z*EPBCKFb*kCG%Y_6CW~06CTP~IfgBVc_!d3*3B`(2WBBHfZE9!qinfs?qE)7A?M|7 z@NnyWC%2nGaCNzlxzKiL>zEkB2^D&KWpm)#s{K#&cfyM?XWx3%G(B}zYUVp|KpCU- z5fT?ALDzVqC4kIT^X{jPo=ZZpTVj3Ku1Ls>OkN^=;wqIuB(t&j%ZfLw9GF@+J1FkSfvv3%USNACvgq2Q&F*GBZ(q@ANNJDmcso1oTDP7;S=ab2NCLeNEz7rjFe3 z)vM#p+WN}(s16uzU$K3>WQRrOWLzyOL(QQmi8p1gj-X(%syPc$Vd`bbkWG;rfSo;d zxp(N#!P>9uxd}}EH4(_2pWT!hC_2^)Q{U~BIo$iM(LV1Xl+HNJVDX;OlgQ7kgCv^t zyK2>pdoMrmypUywO)3oj=;1Ub(QtV|bkj|0`RoaJKFTT~w)XL?D(h62r(y#v%L^TNz#N8n?T05#0Ei4iZ(1^`5O73EK=(2Im}FLb$CT#F-HF;BmhK zzjr8%QdtDv13(#d1#!CyV|-1o4u)G=&EDmA*$Jw0qXh`t1->XA@DbktV1gZHbaTCw zkKep}_3ZVtmoJLvPanOK#8=OszIdHdu92><*Jnz$PMjcXzd!&Aol0pD=CKdjUuAR7 zgX3Tlt|<0=UrB|*?!HR<;v^|7=Cb*wsp-T}e>ErGWP1A7RR4lvCXCU?kyqp7KOf3y zWQaL)!pd1K))!!*CRbwf*6HEUmvIRGTf!$gF47jPoWkbD4WCj>_^mGG=5_4$R&}Xl zn5m(f%uPz_SOH&&Dd5EzT|!e}_EK9IfEwZ5Pj*2UwR^-2%N+yML6rVwe#Q)XwgEqt z8~Ir5Suwf_8^afKsyZHKQ!jjVU@ai_&=JUcDNbqEM^|-9M!!z4Y;k3`W(AoX1Q54T zX}oB%qBNqsNnjTe60Fb8LoU3SAxdM$unrEyN9*lYj4NEP@pVsMhLkxE%dP+8j2@IW zGYfiMucq{*j&9scUM0X*^06cUB0C%MFXOnoCvT+vNCGcuw}*wXYg>d&NbGaYq14r8 z!t9P~?BZ~7|A{mVK- zHwHNsn3Ks_CizHdglA&-IU|J0Z_CQbQQF!q^)p_#dGm94q&q*V@iKANFzjAv+5DOm z58SJEr83V@w&^W4-Qs!G?c!dshu-;nhX=1!u)~b;)FPToGo;nIv$6jDp7=d9%g~B)*m6fGN?Ve= zJ~xxz{lO=-1}oTJod72vJV;mzy-d(6=_|(jMsEdQ_PtN&~ zaA+xY4wTyNC-W{Rwj6$v^^?6H6&?CXj1P?ig}GP3f&b;%EJRR_Sp%`7d6Oz&I;3~l zLAvXO>CF$FvIdAw-uq1*pY~bJpt8>)vm|J|%s0vsssW*6tE_RuXEFW;M7y=~3xDV* z@lQ6U4jP#1m#kO#Y9_X!9)r!s7`6-4u-@EIk^h0^cFy`X?CUDiAmPAvBAIibB2hzRk z|0CdN;7Oc?(l&3T(pR=G7+)&sg?l6QX-kT5B^~T6W_V|4Xx$G`0m^y-$(J{kX_|oeWi9n!p7g$EEqrF zNBkms(SFO4#Y3$l<%KqozqL9wsNNR*6dUm;aZMtiKuBPEqj{4^Ghi(-&P$eirU)pU=;5y8i8N?|K!i@w(E;&QmC5t8kZLHu2%}DF@S@+;G?QS<5=a zS*o*Mh)T~d7)2~M))kwl;Xd2jWlP#H5=t7r|E`asE2Y7UZ{(lO5T zunMsCFqu8VQUqW=gA8P12Xu!`+zk4&w{m`EGDh1E>v|+2h9$lNiTH(sf-Y%C)4IEwpAAsJA!-N7%xQGju%{x-}LgMqeZxbe%Q=Uv9EYd1`!94!Bk}01Hqxs zT9LTZ8(OAH=3!4pfx4zZCMKyN>}fE!Fg;nuQXk8J)M3RuYwDo#!y}Q>@uiG1FxLB? zD;*yKmMQps82=4Z^7*w0a4Sy$&x)P`J`P@XpCJm>O+%FnD|WAc2MM zjj?+|_nR9m;qIGH=hye>cOY24H@~C&fg1ky_VU20bSCsHc#GRtv(_#VY3i6Zg1;JL$dLMELJX>TtSyN$^7 z?m=PtWc2)?qT`q0N1$EoZrzeXk6R|~V7gVxFS6QU7uh{q;J2D6#ZniY{0Yj+5eKR( zJi&V7u6jIi_kw1{_0j;qDOp4-i;@Mutj3U+GhQQf8k!bUN6YVh3N$xQckf!9NFjKn zA2r4rj9yGX|7*QI6;k(lW!WR87vg^Pt4}Gzm|;4w+F_T*@-~J+R-8HQ@qs0zQ{^%= zh!?`?d7%Fm9i-yc+OVHviHS*I=cuS#PFKTv==QKe&UkOV!>{N64Ac7!Dz`3gL^(FT z5#ZzTn=&xU`O7%M82TYHw_lKsIB)Kxr>@Y>Qz;h2lQDZR$9Z$4w;w}F_{K-Y@TD;c z@jT5Y_E2w6*Zjy|{*KMfhSRA$8s!FyQkq%+&J`c zE3^)G`mA7mEmGT)bGV2NYy?mn_LKE8?hcq(V53!`{|$yBcSItMs^Vd6&EpUjL`xkK zr-k2Q&Af%qZ7fDz_sfnPE$}0=Pr9Ubb|eQ86$p^E2~UA%0g@rTeF^_MKegc%83#-X z(5yCSR=2r_E9f|nLs(MUv%V?Aoq_|Y3{1vLz7S`8l)tW*PZCK*#MA$jQB;l^Sys?H ztnt-Zuhb9YsEqM5RUr#uF*m5Vyrc^EU$Qfm3$%Ln^zI#8BS|}Xn~_?qGh14^kJ*Ph z^kjq+TUiD#TK+X_-e&#n$v4kzdY|5}TDmBIs*Xz(24O4aR!Msa6v_n!W`l;$dJ43B z)>G-B{9AF@*XeEF=Rw-=@2=tBdm5tbV9@Gn*#CD8I?1XrYr@swGEl*$U;o}+6jmT= zouL!)@v@u;PBu40k6}}mna&4nQ^LpL^}A<4%;>(5b73=a8?&$6e!)ApBI7P&(e!86 z-N~kIo!M|rak$=-VZeuBG8EF%-=O!8K0D7H2-u7casv+yYctd=ISvdpj6X2WSL$Tx zJ|avL1+D*TU5QCYC$ybX+8abmPPf3B*RzYheZW8M2i7gSdSCT-C0~C0ZLD3Ul02q? zIy!$>%UN$_>AUKaN{ZB*sy1(*K9Z$>$*~`mwkNldzH60bl6KXtG&X z3nzs4(q}$HnmFa*Uh9wUyx`C?0L_UN*N3+{O7aKFMI?Bm0 zA)zR5Bu8MLQAarhYL9`@tAGnVOGrVgg<^6gc2g*z%kzak08jMAzE6&IhS*G}N3|kM zDH|nUNdNYuQ}>BzFgKBGd4n7>VQQMTwvcPJn^Y zn5SLlEbqN9w8@@x$fH2W(SvgjsbC6~Mbhb7q7QcAo_S@gFm^-$!HF!!zCRow?-cu~ z2u>b6e*_$Y;kJ^8V|VP7nb`O+08Bn$^_nk+aFz)#`Oz~VKX}Gc$)SQHN(U}q`so!} zVZi0ukqB`yb0Sq9Aj?2106ME1eRo$kk-)!^>pjB|zFR+R>sA9Foi|@Q<|~jgev%)p zmqh`knE+8huD`O8qw>@k=4FE$6_3M|4~QeXkKf2^>C)<7rC2FWE^w^){)Nmdmxz4{ zde!n!Zd4F~QWjDBO@4bi>q6B2cVD8J(=6$i0Pi*2Bz1`4(2?{9m?s0{H7;4}mf_6) zVr~K{i93o%p;cwDK8+KP2ff--c2{%G+x$R~@qV#gAf0E>x~{FCIJ4bEZ^M|^WPZsA z?CN@WGpzcXF~O`p&XLJ-?uvB3l?sdb=CbKQ9dLm{wWxSdkk2!Ic%+C((1)@5q{AtA zL|?vO*O@8&aRd2V>Ch`NP^6KTRwqJd; z;r(CZa@M~fXEQ6il?*9ta}wx$5YQPHbatAG4C`4U$3JTJ9ib1CZ`SeGjyl399!4Ad zeq%egG)YWl&KKiUL%Ez%SsA>S;djIIZKGgF|(LNeiH^MOA|1mkF@$2XHoHFc5ht3jMi2P*LJ!MP~%Hrj%`;{i}k`NKk> zhEt5dJKDDG9qHKho)cW*YYemE7b4%mjv<}QH&}30IFGu(Dwz3z)SISe@{mq>1K)&L zKb6Z61>?Y@Pw-uoHyUe(pB;B7df*Qt{f!ieb45UDYKCn*cBuOvhCS>h{xXJ-SQ$|*z}xtv&#DY%5=y=Th! zp!xT5S^7-KNFCBhlc|E7hB2GfK>jz1rxQV7L^P6G_{Rzn!Xz}Us<8w@N6$0{5;BB_{+huwcnsq>MtIVUJhSN3%y9a0X` zJ)g^7Z7PYUtpaVpaJsE&Ey=kb|Ar&bBWAaV0Qj_rug>_l$`f%JK*Q5rm5B}mFV34V7|_*&7#nCK5%z>2=R>@-MW(!t=BDg%-+F!4tlTe$yV z#3jhZwwJYwlOAx2%qYHmonOlJQS)LpnAc45$YYn+bNAB>wZVxRKSg=IY^VTlQIp`3 zIR5(G^Cs;<+bxG0dhgW*_K4*HD`B$GJRt z{Sc;lVFFqknqHr?BZ}T^21P-rWHvnr4`?4Ws8zLEHnf7fNy8xs+S=ZBy=SlE@SD1f zRCU1)1o*T15kQaSPYOl0OCvR)qUH1AAzvXE`}jgOL@7ps!ZAR|Pkao2vL27}QuU)_ zvmIpi8t)jBZ5q)BU@5;0bKW1kqNt%8s7P@twG$|x#EvnE>Y}0>nkITK{-cNC{sY;k zY5v58$KprPWOO|0?5q*HL$raaR_l{uY43G~EV(O0CkKri<)HL5s>OC=oky-|_aJGW zk+mE98!}{{EpZ}98I(3N>KrH4I}l&C(Znr;w%wYr{jpML9ynoU^j6^4YZ(}H@qS34 zwI11<;M&E0r+hNNqkip^U{>cKVN>hF4OkyAR77l_UwpWjZx*5y#%NdqQKRl?7P+{m z$Y??$`PR3d^r=faK2Df2aJwmyTTXzH%ty>rSMvh9M(XVr0!-}uT7J~8NOEpdr!!)J z@VlHxH)UO;&lW;d@zDW3h2h?;sXM5ip?nE~JS0KF&EP)&-ma;_T8?E^{k(4)X;lrV ze^jk-NuaNm*MVd}g%oH}#Pfo>j1ESSR}Jg&ZG{!V_DBNe7J_WfS3-=G6AzFfl2j9Y|H$U1ifa+@k}n6Q$yFK#D+0vzEVkrVcCNR-9qD6g=qBMS zrOI#r#>0U7UPtAJ-q$ON6?P@~Ch3lYf{zxGAu4S%j->e8_2DAaIxR~HJFn@=YR#qX z?|4+^SX3->f2a4HlV=z6nkNCihy$Cnf-NGRyr+9o)wujQuj=;+s8uP`x``JYAkcb4 zBZul5`rgJc%bf3~g_6ZyOR0vwrhstvijT&=Dvk9uzJdws_P|<~by9GY()x5=xI1x% z=U72a&{8e6W*3}=w#$cItoOTEv!Q>QG=3DeWtw@Q-UYGC$q@3d%43msxL=%DwuW57 z0~$WSmqzh5KAC2ca^$UBk>7&cUl)rKwolnfxZiPZAZP1(eGG$WaFUu6&^c zAdmI42!`}xeGzCkKbEVz`PQ4Ip=|N-VbG}MBbQBR)RG2#R{SlJ&YaNImF3Xi4o1rx z)dXvP(__Z)0fMJ{%j4|G+-zAXBW5V$S|SA569P)IQRLa^D71w6{p*l<6ixPL8 zS)#AY)Eki8K%H^2*yB(p{xFa#TG!OG+!+CIf{H*LO6EjdO;hEQp~evQ3(tQU=2`>I zDj1pS^LgXMP%KrTzc`(s%ar%X4O; zTrsgjpDs{kZpbtMXHGXww?wmrU&-l%`Wio3>7XljmnFfO)*M2*J>O~gz`Ri7M?dO7 zt+%=vVUbiThi%uIFh2yk zJ;sSzj%NynLjc<8s-(5WJSm0G?X@l0-t+=Uv+#Fnz~+ZC2~~IdAN6h7XzOUnNdh!9 z0hvrh1_0XI>vckK=g8)sO%4nCE%O44vedu3(hkfPk}T^pN{k0l4?ctJzpt7wfkdbB zYUQKLSz+e)A*J5mc0bRm&mrva}?1w zpKZfJRFdccM~z@=7sMslE3BGUgFF*;s9c1z#5$~a0BQDmJN^YH2?LeM_$b&z$l)i# zf|Y+3r11l%uk?tGnFrbJWIqVtdPL~i!2olhzL%%A4?=U|*s_h0%De^^2aLF-sw}f> zn${3@(r!NY$vUpXb~LEA&sx^cI__F+VPGegleK(|blbn+_yBaivhRp((m$H++IMEd z0z)XT;}PLO_fCCLp3KjeG^NJG5_Y58#;1q*j5GF`VkV>3Py1R-F zF#pVf2|kRCO@{a$+XSlA^v^hw5WY36j|>J)Ld7L0Gd2%YnJ;5d17h4S2!H=)^CZh* zp5)()56q5XaK-l!4`V#i3cpwwRD{Y~B*>*}xjNi@TOT zSU<^GGWd|1!24t*p#zbL7R(?xMv;sy`Ug&csTuJ-~)J4;#1$Hcb&M#;OCmZYFtc);(dEM@IPwF$$q zYsch%d?$_Ku8Oy^^=z(fm3b@8B4@H_PgMf$mW;hJ$=JA6o#zwcU9Q-t1k%(ZVUmu%o>*q1bXyO{4_C@GU7j z_Y*XeHO~$p|5!dvB$%!2A0b5qxoXu*m_|145%jI#@sZI3XnzqfJb%i}Y}Oyq4sg!p zfU<1wu#ZX^d0E4*S0P93I2aEB|C~UYXH0TRrdSQR@duojx%qX30hYH>)_Ox(T`TF= z8AJMXa(>0*&gauB^TOTk_jg8g*K`-w5z^VvC)RmZe--l2*kmicw|;l}4ut9%p*jO< z*$#Xj?d-dI)*TLJ>Y+lYk%`iJg~g0dX#1P(m|Dx`I`hQocGlzuJ1(mwv9-4^w{`j_ zVUvW9x(wAlo5^-yTNo+T%hGAw`5~uTRn6;R*@K~_md77L zOw#a5W8Um6xVYs4J;G|3*NBAzTf($`6v!#88HK7sltomWVHH4fq8~vMj`|wpRN|j( z*uE~8^siC-^@hn=+UFeeKHqH&8Ss6KhokaR2JXG;!J(;41T-Y)Ko)p z%*{%a@I`fuJoA@~V)o__e|*c>X5_G{hNk*XLi?!qz<-_#7c4KEBP>GPS}*Iek>z42 zB5KLK;iakZcdcO_T8n8~l7Pq>%2UK$f%f{?Pm{EbX1baQmf0c%zD3a7#9a0M^^DfV zS9+pr2u^9K9}_niI(t8<7|lV5C-G;N=clW2n*~PQ;OxdKv+*jVMB1}el!S52xIr-} zP1{ZOPV+bY$;YtcY5rfkqw=IQwBJhiihX}P9QK_i#?oYLMadvIEc z2DsFRPqm-U67~tKR`&e7ffX#wk;cK+P*EwGAL=`;AM>9gR#emSQA(* zXsd+caY~<@4kYYjFhXjo7B%KVu0<*xOZ&2uicJG$$75@>1{I(Y#5g_&*N>2hYL9JF zN4Bra6+&leHY;Y?I>qvcW;M9^A+F*E=Y%b`0B$0vN|0%SUG6eKmS1U!gLvs?-JBM& z60O1WOG043KwX~oROlTZp5|3NP~VjA+F)nJm@bcOFQ2M9xF9mlELg_>ALFC9WTKROrO#))DRjH`?NFAqV%~gxcjMpMb}%XwMf;v+*IiPZiipJp zO_46mAbGW@)sJ3;+0@*SkSilNwYp(3s zvYuZ&w(osv44M2DFk9W%) zM?mhyvP?+;rrMDPX+xpwC-WWq#Zn@mYZH?I8fwnuoFu1#aY%0qvOI#X2{6%md|=sh z#$S`ztdGrEk>Dr4J`?vRPTeVMs-YFx-=;~mbc}@#O(%J-%(Pkz;%43c`;t9V(<$ag zC7d^EPovl)3kzRP$7qVh2xlgZhB%^;0hdp~a*sb~2^u+Fsa3g5s^6{jz_H|a?wodF zj?tf(<+eA;ZHDr@)7`3J1nOimlp#eTf6nQB`utbB7PD!Akrmj-u4dLBqI_kC^9?Q? zV_Q|z5ka+EDD~bTVrc4q`0`{dFm&Ff+dU(#<;(2syna6pUpt9|A0w`EJeoRH+$`mm zo&5Ia50hR2_ie*i;urs*A9}R6Z}!UH^>XoIiY(&tUwQXNWW6)4ojo=(h7gF0_$zxl zrTXu*Kuj1=C=PSy2*u5(tS74b{3kWgyx0$rdwo>&93vR_Gx+O_dC?o{ z4CX?1^=Snl4%foMb=|8?b`Pz+INUcl?5Y8K=?xgpH!DLSPZgc2`=Ib{*kly%6lj<= zM-AWi1Jt|jS-=y6oq1i`owlT=acnqW(N}yG3_sDrsHZ11;wzZovm<`I&RY!0nz`2xtl;z-n&DpQ#b3Y56+&;#>i6r5wxat?hie0BGV$HH zN_5qh%f(INYsVs?JGSw4wZJYP%Xo^&Uo4wsP{vbAjwD~o)tSh9d|{OtAHqP#?RZi? zX?|*x@gzdRRjG#*?@xDumEk983s^JeJ@T9tSw~5NtZqW9*bwDmneOasAG%^ViM01F zyK2SY=?p&{o_0WgzZb>I+qG7`-={I|jHZp$6oH4$e4JW7Vnv`~Zt}py%y)&L9puB* z%L13HEuXV4*tG3WVjM1}mY0kW%!YY#(7y%91o)Jk<=|eKRqKhsg##41S%ZmKn5uZTNu*27=J)zlH%UhblmN!3RX@U<~CI5wk?(4)YUHVny` z*i>J2LS0V_@b8LuvLUeX%^%NC&u(JtJgW9$?3FoRo0)|ZU_bt)6fR6jt+;iFUua*3 zX07%+8u?m&rbr4uU%nNm%{IdCY#TF&hVIGqu}CLz_NUJ+#J=oNr)SNQm`jX^j{oDl z$$E2ye<6IAa0Mtvjyp2DUD3^v(9}X-u+=G|(3m79RN?ZQfx{5(=r)N*WPIzP>H?^(WuaUiH}4*1bCc z3inKi8bf+BIT+964gUMq5jPt{EtN8{4|u?ee8n5}SNv2nxLM>)>?(H}1~qF)xo)3d zrp7-zdbn_E&BG4+_SQ~GN@}!cg!5+LCZvO#rF6cf*Q6z*e6ejeIe=@s77?bwh0vuL zFit`A!eO90^FOp=@>RA4X7*k~+G(K=(b7-p7U`{+8e%eW zRO?_a;J?<8Tx$6d409r6+~D z8dq%^oD>d+V!^O~3nhvV%3244L~tVmlPO=N*m0WEx%IQ-=yt=Sxcfj2!ER(HAjK4b z9j;x{-N=laxY}W(z(MNbMl5!p2W~xfk$`S~okTM1DPi4eam<{44;JkPUdrR_SI66h ztBOHvoJYT*uBjiF8<4l3E$R-Q-luLgSc0D6bXZd=W0S6)Uc?wWO~par1j#*a7l6ch z7+0tv{g}!Z4;H1@$1)4dW7zyl3cE`@9os(t;U4NjPxsv|*UdFb$KGgOS>R$JwJ;ic zN@%VD&`~%19Y1^N>m1$=>wr&S^8c31Ev%njP z`PQ^>d2l&0Do&<%>Q#JB?gbB8G~wP10E(ViHN6UhDx@yb-%T`$JD3>iS`K{jdOc=XZ}HE-uVNei!bnz_ftu}9{IQ} zXD4EOs!NxcdPj%&nCtx+UiV94qi9kJD3u$Vr)ibkKxsurwOlbIyG;A8OyTb|S!3KLuxs)TUFz58WM39^$7nJIxi$jSS8g3xvj*lok2O>B09su7A6Z!=Oy!3M0 zJZ3MCK2(N7c322@vWL1c!9SzGx<__4v6Y|I^?6zR%iTYIc86GzZ-($cF6HuNLH18< z#BL+<%ZBUh`l}|x*SoRxk-*!5t5dnKIlV4dD{_9nBn-c0=BGKkblnWq@2it2LcAdR z{EkhpGUwA*W+~7hU;6%hgP`6UMx4`Nt@MP!=ZY`c8KQroZDA=q#armqyNK;H=E1WS ze00v%8@n^)^bUT7eBk?;&a-iBj=ZRn=M@=`5p9$AM3Tkc@$NFge|HZn;zEMaL&pH( zRgH_#A^p?IDIWvUHmS|=}3oZ_M+iB2!nql zOcm-rC}wx=d=BFXehQQ9;deH^hXS8AKsha@?)Qu`pVsc~Y$(URV7jtP^hYky9|a?= z8JFjeW_jj1X0taxzMbqIK1QRfVHx||aoa8L%{0zh8%gFO7x~9gfdG>Ja5E2be;tOK zjzdWGq8qXz3K#v6{dS) zBNg`&jLej(U@W6;yIXU1qSjfvM)~dax~Kk@2G(RdG#&UC4cB zwJuxL{w}K3Vtv6B@f8xZ5lAB_7R|#6hBu`>g2Sw1%yRX_l~28aejrDWO2&NrKJ-RU zLs?RGH{0NPzHFj8`1JDD{u0e2|uMrtf~xmKH1AXuVu+oQWbN z2&KY^vw_WCfF%yV=lAa1`J(j=^iF`@|IWMm8B${1xrerU1G((;E`Hv<&k$T-n(5>C z{xS!2E1{0&4gIg~$@n_PP{!VUv0dl)ro~YFW40Pu^Nf!WXYWbc>4|OHq8b0xMHFW} z51w(LJ@`~HBc!N#>Fjeu#01JlczRkcp#LtB!AcJ2)d}oc%v8sKhTAqpB$8I1mL_N_ zvzl@mnVTu*j z4E*Pk=`+_BY*mEG?E_zCn!fEYI>JmT@v8_9)tK6PN~igYsxH%y7AyzBuy;Qo`I1cp zWJiJNm5Jb4j1bsXdwdvR;0Kkoete}`i(#?f{Aj&iSd^vv)_K{&`T%9y*h*!RFt&vrz3J+eRtd=UH0>H? z0-sfLF1C8-RY;X$0(JuO;&@9m9>Lwgqt{ zw~!xlYClDN|9)AQ(6DWU#i5u$Uv{ zL)WxpQaA8RCrQ2rI9`@5{by~g_*G*DpaCxq5xW+fn*kZy53{{9!8SKGu}4*_Mp0o) zO|W`fGG|o(1&fox8kyIS`AN_x@<(M8LBa)=$j$K1@3`vK{OmcEmZ8A%-P4ad^JuA8 zd&rYzx#HLKN|}FqzQbnaKjy7kX>aX;FOFt1@c26&nm;EzXh53Lnu>?^K*5TR03w^> z6%j?18b)vF5$CVM5#vbi*mB@bj9&VwFuwh_Q3SKXBzfTXPhQGP|(Rt!67lC zmtMpwd&E`pSqdcz5SA`sM|D8~Pm6IJ+CwuKb{#kJJq4TWo&*b)@+0dX8(Sn|-SaWj zjw~Zv5l2q;Up*_EuU%e-k={R7Oq^muCX>G~2>iob(vJ{t=fK#S*WdH8WdEr&&Yq1o z(=>|2v~3UVF<9HWO`)xGUmT1azZpWQJaOE`)@DxfP^_)IZNC=>LyiVA-fzteFOnk; zu7UGezIy}WmhTg@X-SoT$^Rs>3NWS+k<&}@e456u;z5PX!e-1 zGqETwVnAMK8V9 zml-%Zb70ug4_sH-N7vMM+Rsgw+Hz=={=s~H_OkP%Ae8f{GR{|q!QRj70+xK!P?bz% z&uy+F=c{0bvFa#{YK(&v7c}h^gUn1TKVjUgtJ9!R);Ak?YP9RK^5OOsxk%<`2+EFR zXoQ0L?C#`51fTTCv}ioosCYt-s8bn*43zq=+y|^TPRH$~FNyC$)AZ5XY+UKoWhRIg z|MV?~Nkd~;K6!r9dC+l13ll&sT}$7(IP<1eV~EW2YYq|tBxlClagp`B6$k)l8p}X! zG2ZmUiu#1iTYP%#J#2wO!p2_&?#(<}o297ktvmMpQIF87(=#Rt+=-U^?&a#(?5;@M zg#+FkE3r+xQ|o{Z3rR*4-oi z6Y7qys#AH_nlJz-7Vzz(t_TxS$srvR@W)NEjNOV0P}jW~@0Zof-N<_>NzlmCoWLSJT(8JJX4q&~0REPA>5a`PNOxG1$P7tRuLTnoJ$fNjvp z*0zZJoU9bBn=TK#Iy7q)BW&`ThYMxCl)b?11kOmrDXwaiqN`n|8%;7p;vp$F<)Mb9 z=D0R>fgtJNIoY^L<>ZJ$zcU90;v_c1)XM%Th2cOHug9 zzpdxS8~*Kr@r`78>|GG=yNG_&Nf`Z8Tw^xdbg*7)XZ*2SZ|a^QJNdsJ6zH2J{hhye zonv4~y7r7gtBHs$*t^S$fp}w7pV)#>zbRR-!uRNWB)ASeL_xh|h48cGE!K(Kqd-+# z|Hx&C)c%Ri4hXQKT_hd>)=3oFk=`;4BSBumTY_@&zsk)z0FO7)kfSen84)h8=9H%A zr*v^)aYq(2H{l-(2}-YsPxYnu&myGQ}jo7|CC1M z!|vyn*h~)A+cokKG+C$YdK@?VfR+2$g=z@y=3AmWJkU}*Pw*T#NZbF_wdaT&02ZeZ zYC??=I`YVD^6V=mC8^~?FCHz|#~(;7UoqZy=;$9R5{#FI=fQVkW7?L5;fTCJwB2@K zeYLQnbsFsUNJ4(UE2_XJax%qL7jjzyDd-vJB`?MVnRj92Fg}RHoo^PxU*s!02J;Rj z6Q;9&KK2IY!wyiR#`$Ovd6KiiZkU3;?hr=;W>!jmer-)P;FDwW^XnS(RwPoY*|gc# za|HpXOu@1}2VzfoIOP(LiKiT;Q*MfFr*6p_T=Vmrq4{WcJo_j3Mz3gwuF?M_`s?r7I!$*gmV9FJ~M52jcHb_hh*Iak$_=tAb@tcEqe)y?k;s@{R z>@akkOLiPNm8@>#MnSsPuoJdT#tl^L)27q;aX3!PzdyVyC3kdq+w(Q*J{0BP9_5==bPQC_Jy%M?rF-UER1+@+K2O`SZ`2M z#u_X|$B_RKhHu=wgGM5FY1T`E;zL=USu_gHL(M%T;(TmZe^Ew&* zXCEfBGLCt?a{*Ied*M1R9<~n_nrXlTAm+r94ya|&g&4ohLkczA--Z!vKLf_VVN1=5 zeQ%mRlu@(;;GgQIn(#sGSV-=ldV|3)A0+9oQh!-h&$;el2;$Juicdg zkLT_iuWy>4KHJ9M02#AmR9urtMxC-kD+&A|^QGC&jn}ejb~a2$$F^0lCiP5L)ja8S z=s&}QCOd{)Zj;|*!!|hG=tT++1r{CF^7#0iC|80;{{s&*jLgV{_3(Ohjv)QBq%f|W z9oE}@Zp>5my;`nm-fz|`SjDmPoXkI1V>s^^ibk8+%~Sz@V=ofkY}sC=@_lFw_>2Yc4`N z3PGPEFx#4qi+a7R#I`0^{58d{jRt3M24~vlksU3Sz6|O`_VAx+K>T~ryt3_ur*iJp zyaUeuG@PK7F4SI{pEqBAkFo=lF!%9(=ONWqGJs)w+MLx=26yG z_U0jy{P|imk?1NmqWN&N?-Y+Izr${iugR_k!0E;%R^hF`E$hE-WSw>fdOvf!?B;Ij zt*JrS2=VF&R(U91dmF@&r>+iZ-x!9AUtVE~-kLa9tF?8b^;pVV;JTEEV!?qc)OL8A z1w_l~H;g5RtGMG2F=<|lE}fY^RCMhM5w&8T(N)vO=yZ)ZTjI#re;JXFJ@$(OxVgZK z8oce!Bo|s3xI;C2w3Yi@xppYWqvO*(xpvrVHYz+_hV3d^8_eLC$6_ui0#khfB{<&L zOO*V}B~4)Am#lwB;~OYq_Nsn&mS@Q)bG%g$UaEg!&1Wn%?|%Rdsl&@nRfc$JngW`x z#|%TD9*JNMaA18dk0eTXt=DjL$j9%4Sq#}!8*b@hLgt%=bL;GxlFXnQoD$eOq zwQ4?Md91;t82Fk+J^&d(qb%u$aHv$XcC8R^nQzQhYAc-5&*@)DZ6 z>sKN0Mu{-$_sUYo0^sC)3GmAjoEh`{0(vnPWWgD5iACvzV9C+Q)KW8owdwAWyk4hg z?Lt?~6l2ynpDb&PGEFn`{-a~rktOEsSHgiJ@SK6WJUEa+ zjcB-+E^Bgp0ucrW?8K$=UE;x-7SBY#q8C zR9y?KBY#2Ao|VVdNp&2-vpP5K4ize)@~vA@76Ia_`cJtlef9*BCq8ioZdUG4+DzJ9 z+2OfI;*dTi`RNT_st|=#WSmiI6AN0Nm5ozzSFRSeQ+opE5Q6FIGXac_W7h^T69t)kLG+%99`Csx@9jRYdre38hCBL9 zJNnFZ^w}p2O?&)oxX0gXkH2?4{(k47ksq7Re*bpx@qwRc%UN($L(sfdjVUr=Z^Pi_ z^5HB!PbR`)mTU=$s93PjJCjQ*cq36AAwou*f?ZKcjK;ze|3ulAQ=Esy+-Xr8u}!G& za=<$X8nDeL?w_D?f9%SPy^;ebojBTL^wN^|g@nsOoJf4N|F%y%EID*4>D9g88IT@k zQj&V-eZOSMITrgxgJ#bt(pLn}PF@5r;W2rQ5c2)%3jSn{^-QVg5?^T%xgsUz2 zjIzVMVE&QHjz+d%JorjfqIu1PQf<5>{)Mj`mVhy_EdfsN-fq_P@MB=>vW9P!Hc4nM zvPfz!mpCRe_JIkB5KanfYf0XeVj~jk-qw_V#T4sK-KSKmx$lCj`rb*$Ihc-kVfJ14q(L}T-a*!17YCJTLs9+QAKnh%>@?*cEgZ2GfL zWHUuHb7X8R1eVF$A=PP5@z5jTBM_T{hkJ2mje2eK`de`(J^4;^a<*2TqWLuT>O*so zdvt_gzQIb4^IN&Z(RVx7eFxJz#fO!7MO}V86O(+kl>ml*-wQy3(eQ6JF6TI_dg@{x z)=6z#(4L+SdrJRqPrDrLH?oz_-w6qNgG+3atsN&9l|W{kedCC@`L~<4daFLNPT#t? zW^k#b0VN^-tFRl@>Y|LcP1g4Y8T%l93N@!*&-}P`I&9n<4Yb!Edh!QR2hOCBA&PsB z6_b1&JTG@;$>Z@N6Q`F|)Ecx=!z50Y(h4teO)z#kncY5Lg@22q%Ww$*mS1n8wkY5= za~ns`R$SEqk*`9*b3%{nSX#Q8-?2#Rn$^wnd~AHy@lo+j#5Y!f2`Jdio4U4IOs^BG zPD4tva@2Q4)n!=WWH zt65VxbMK^f#b|;~msx9k?@xim@0#1oHpuA;Ev#5HYc{A!*Q4fq)drZecjAe0uM^zj zeD!Sgk}~haUY19rZ2J0F;Eq#l{VkGeSli9zaAVj=@FZAkIP+|GbU1d^#e8sFF>oGe zpxORo?ZgIYTA6_xEd6b9KTS*%1V&zR!xkAA^s3q^w;5t7xps%^shFW7DjUy4W9-M3 zZGm{jYhF_D{*+w5J{Bqq%5s#ir=)3PfIpQFoiI-R{W4$*Z|zE6zV^ryI8?e8iP69l zIRkrlGP_PZp)Ex~&*wW6#p;~^uO~zkyqUR{e|?hWxza=ab@}qEXMg$XYx%#|#rH42 z{kNyzCS2uWaY%TZ#3fZvPqH5@gDczy*}KXOkG5T-rppK!+XWYC02h~TQBB721N#pC z5rfBxPUZBnY3N|kkM@JZe!R2k2pC%WRjFIwY787;oP46Pi_9jGqvLVqk0r_|DYzw@^1&GNyjG^7V6xxMFYH04Nn6 zwhKoz+Ph-|YJ^Q3v?LwTdbtQbQnjWfs>81XTZxzTufQ&>m1d%TU?>d>##c(WulXHe zu+J_-^FV-8I#m&Ua^a*&K%I6QCjh39_E&SsFa;(ppfv7{5~;;JQOiv498_Dc@5<3q zMk*V;Jh@2I$IFzU!QZE>(@amot*mDO9He80isw(9KY9kA0Tro`02Y}#5$nc)g| zKDnVo5^j+rHc8U7VQ3fD@N8C(XEMLx-}COG#IV(tq{k+;QN zWNaE~xp*sZ4SAnAi=tcS_Yd<6JsArwBSeR)?P4XkxMFu6j}>(PT6`W}))o)baXJZ- z8?MzV?4I!;&HmuyV0E^X@a&IZt+D_?)Eo4nZ(DIg)S48OTFKrSbiYlL_SW2M7|I_{ z?McWgV|kAb2hurpkP`2rA)E7W+wtrUjQdW&&WGd4vsd4I{pjz-lW!k=FWH!)3!vVj zx+hHjdR3#sHSwx;$^%O!R9l*4Uk7bWSR_7SbcDt_b5Y)0E@{Go>)D3UIG7^zV!qm@ zj(2n(LBZrVwo68;JM7P62RzeMb_QJ@W}ekF?LbU>`#~BOiS76`KDo$ejC0Kbw4qk6 zuk}(b!EEPaEt|?D)**?OJiI5IC_7DQ&rtP@p7SYhm{(#nTqMuL%F_zo z{>dv`+Pvm<;~Uti!%7_lD9O8LhM%v*h(?dWcZcW!mMi>`aT>Ci^siTrygA@7To7Ti zmGvC*?+^N&My_06Cfb5`kOsIj-j<{vQ||SK_B14m^q6a2?77d5Ukz;k&L}=VahJjN z{Yl@YC5^)Ifzn<-{&_&=r4ycB5$PRq@uap9Cj99xUV*)mfc6OQ=HHpfl4ugNJNp?} z${pBvJy{IhQ{G^4&~|&v)z3uVbQ~gN($ z+(0JdXQ(Q1xQ2zX%XxPCszUhtU8hb|8*5RUfBpshx$&&9z0@DB{*gg~IL6TwG9%cKcch4TPwa+I1P76Lssba$ohvbo-7j6whwL;u67E?B3>Kf#F zYTRq*&y6r5JasMoC1{6RA7E%?E?c~Z;M-PYff?U=W!+`tE@= zVCcz!xxYNJ$%%lAC)!WEY_b}8oH}r1Yz5(k0w=h46^OsSIL^sZ`aB>*ccuFe?s9Q^b;O?1<(qb&`V4R0LJp{0g|Fc=WSKGMxu}!zEw& ziq^b=oWoIGmKxW|yigy@X4*I{@77zLw8p1N=AL6>%&r>GS@%NQ7{=6}I?P0+PyXYa z1;vIBH~HS5`BzR#@J_pwxr7xZditX!VmTv~y)pjxOiJPS$+NM&)v`u!{_wM>Wi;Hcyw^Nb}iv^1F?gqQ1)mf~;!hA4JXtWf=IiRb0N06GzQmdL!=-qh1 zo6|HpRt&Qv?eSrTzhB8Nf_Kg!33M?8K0w^sVlHHpBhDW62+bw%@>TJ-;`{RGL$$S= z$3-Z?_QZJ6c9A!y-S6={=C#;oaKI)4c0{-WowXlr|&1yrfa^!Y{vIj^E+?g_d z@~4%~L>At*5$N`{=n94OoPWh!hE?#Pp4~3}V66poa&k-kJ1CJZBKOd5x3p zyY+1Nav1gcZ-r42aCs;T73t6vCsDu7^kv0C^fkK?zX4_JRJOoQLUF?|XGddwvEEWG zi@{tXSMoCI=v<~Q7@kN&EW+3m|9ZhCXx*ULTW_d0kbB50ia~{F&n8;&!-cR=S&XGI zhLa4HLrNAS7MkhDIoVk;g6d}NW2rbHqe^)H$NLQce2tj3ASnd=oHn)*i#}^q$oKQ| z#MKlPg2&4d{HXTsrY(yEGpj3k8n7}?aMWlv7sP+%hfH>Q1PZMM($G zjd`t#!8^rFd|axbA&LB-`djp;V9R?$@L@b5sgcql5ugW;JAqNkOs8fx!}h6`*XEVi#^ zQzfT2rQyyBP2VQj=lc^n`97HQ8h_vp`Hb3P3?weN?3M2XKm?!~X(3bl6_w(#H8^Cl zF5dDH1ENZ%8R+s$!KeuUNOa=FUVpD9Et?%$cVibgG#`yu>nRkX-4){L*EA6k{z(OT z7W5Yq@a|nu9dn)7dRKMVznhYQTMdT120K@0>qEIEo1KLp!z{=@_X#de!;f9Z*Mb$^ z{P=cfbe&twj#JhzVG@>7eoTWJci+P?YCsHgWF6>1g7Ba$jRm1G+iTCl|*_5I4;l+p-=nZCTJ**lbGty_n^RsJC2rX1HnyX z7Q(~AvckS-&pT7bW9uA8y$08EW7ogO=NU6A$LnLVUlVRUCf`u8wF}VsUcPy2@>|R= zl4~0Fli35CUWSjXtNAHThO7tIWy_L*bn!CCY@YD9UZ1eBti(~hg`Iyy&}m!L;T%M9 z&UXC7_ggRIuin=tta&)F4(pMNi{PkfkFnK?v*pgKgY?DxW(@nBBs#3OaN>~m!w{z_ zP4@YZg7S_go%8Drixfw-TjzsBa|mI6JwDFe)F{!xlF*kSJ;|QVlZu94!A_ed=MeNX zZW~Ig=3vy>)_C2m>&Bm^lzF`pX$C4GQGA70DDAx*=65|Qd#Pd;MgPiUkNr>LxV%rK zE-Kk~Z}<`?P`*now?I&d6UPe4;vzkQx2}?r z_PDNJ)B1_u{p*=D?F4QgxSBrNVHTh^Qg8~OLI63Tf@j5}; zH7RsxS;TR-cqU#Ya-CjF)!^E2%=n4X;2PuGYyW$jl3~T`t-BP^%Op)A4xN&iObe=x z>2*MSzY`w~5$!`ZI-olyQZzRSxb~RlrT$OJyi0YOBR1(K@Zn5E91{igW_}U)*`*V! z?=g9vzSDDncFg|Z#{tPn{^TGs$z&>cQQ5ee9IbwIVq|$)PQtUZ?W%onr zAD}1d?H6IEG5*^mx5Fi(*>i4HMtLr4XrWh-$o0varFMDI?}fA1at1!7 z)A1%i%?*G(BIyAambw!uf2h@Cic}_RY%PgRH6}fCJvaDtMv0nM?3yUJRMo=si&Fd{ zt2IK=17wpx4$w{nh5Z6~VX@5PVZ1Weha#qGVIq)gE{N83>!T{WZBv$O3aPUc7TdMR@DprP)5P~X%JD@JhYI|tOPMb^mQL$X)3W@u{j z)n#XYsCU~M>Np2pU8byZ{&Nsie(&}3&Pkni$TV#+eA~Avcei4|ozYChny!BXU-W^WV<#7>R9&k!k?= zirGTnjJaS$zdxN*i8)%I(`+5FWi&>MhYit`x|^GY{8cyvR06vJIxp}JV3|Uu&aH9Y z^@~bH!K)jQR@ebNEP&HZ2#*&x;(picu?vgJ)6+9a{8MA|!;L$WY1b3r^-~#Xu8{0g z6lK(fcgJ2hXX{uu?=ijb59^csoc!g0`d8*^-?Ntw>(%m-(do;9%LfvCRU(|sd~?af z-AZsYnV*V43HvZLiLjaB+*TYx(nuRBPp9(_A)vm7*l$AcG-PxJ-(DN@BDLz0Oja>4 zw;WJ(_S!4fy{HawkbJ(-ZpqZzXT>9&IKyG_wE8a|YHb6alew7}^#@WmAqn?x(puRq zy<*jgP%V9qd^Z@84pYlu05Q|d!fz-Vzp|re0xQjofGj!0xiK=->v+B7E}g+5iu54;I%78?M8Pmw>o)gW&1!Wmvx}7gEE=Vu)jT}d`|4`)# z0y^v8f9Kz6uxB6US?Q&0QopZGzy-49i3t)JAmbSMsf#PQY;H2}&sWVE;eFT(VloQ( z7z5pjI67A#~5 zO)2A`Bf}|*qGzcNjRC+l`i^cHB2bbj;pI*bG4(Y#i4LS%ldwpdVL0h|s=FPt8^pAZHw#AMuvwuP*Y z^(=hgSE!8}!CQ!WQN{p9A6DxND|zP@LuMu6$m0Dj@B=!C)QeMvG=cOzPBKs$3*Ql( z@=Q|7sGgsQ+|4(-Tih-_bEaulehQv^0?r?&krSZ* zmlV(8^WV(9{blFd-_5N(8b*gpsU^HIubRJ^x)yD}dim|M|Ml|4>qlSz@aS*PUYYX% z`(-Qt0Q_6XXw+>6(k&!geC|s@%38WJRdsVO zy3k#-?6unv1dU+tp=gckvMicgA8zYa`ut zS(c~EOQ>TrUM^geR0HO#$RxEK^#W`0oPXOWwo|FkU7wep zW_a4X9i@=C5-z(1f>Y)p@t9gtq}wX2WtT z*Y=HQ?z(|nr7iySg4pGSAqXc5^10e=sx%{zSOKngvJ3R|J+Y5@^0~YmXx0Gik3+D@ zdP32&CJ?})Jefm(i<5z|>Ya=&t$*Vl7UN!!uXBr+kn$H*EmKo%$*^@7Obg)03R6Y_ z`8S>k#cWBD$W7>P!ANi_y)eH)P-Y^4s1G6_aV`4nzkK%jAOAc_p7}09(yrX3l|M8@ zctRSC?L(?uDkNh=r)W2ZGjt9ayIH>z4yzT8+bnKMrlcQ5H@|7ZPno+qd(Fyw3Z6u2 z>elHJDi>{Hp`bBel+@#?Ed!V?)k3(yN%5VQ03@J&kg9E>XLv`Y$AF{ zsCO$Lw$;vSgTj3qda7V&c3BXtBD^PI>Ahh&#iRdu{}f+aK!|VenPlhzZ-U=`v9-ge zGr>Oo9ri%8$3Po6DU%T_QI#`1?B&Kmra`JyaVmX%V_N#?zZzo`HB1$5NN^zHdhEl+ zUU#T&sihMYc{8X|y+kPX`p9+A*S?P?z0LpLZC-~NmF9$l6_^qUMf&l!`zB(I1Mm$) z5kIgLPciS6#zE&JKHj80|w3=08A z$6I+O#^=ijtn-9CI;yOXAmZuTQk|Zj2P2yp%JF(1Mi$6(KD=AdVWs zHWs2afWQI_1rSzy>={c2T_Kn;woiQ7!UP(8#y8Eo$2!;@`IvmZqB9y5DO~!9O%RFa z35D0L#5iDfwvp{*b7_znqZl>N{$`zSO@zW1!uTGNmjp+QhGXEbx;>sm3z#9Ii6b2g z$2tb!5iUi+h|v{|U!^7gFivW*zI=>-#~|Bn2PT}g4z(|yHIcWSzDc`zn}=PBH{7yL zK(C=mW#eUY1+rps$Z|HwImE{%Eppi8Q*)9+}S#K^e=W13^z=@ zqKR%Q?SGwxiSON&>6YE`=^0~r;xi*Xfm#omn2Yk61LEiH8Xxb=#~y-KIco0Rjidx} zCVWfF6hp*>C=|A|nmd%%#WvP}J$sqR(i+x~x(R@fWFV-;-jrsMn%q zU^hl(N|1fli(mMYQYFo+1^MS#kN?}-iyvIj4a-Kz8D5U}_9{8*OwC>ngdbv%`%O&X zP(Vt-Dq&2HS8m#VmGlI=2o{jo#*5z};BO+%NgJqU{Ee5uJj2;=-#n0LP-5PnVB5o= zbIlPvhWpgb?fRymjwrX=%OD^4cBWR(XqlcpHUNOGeZ7Qs$Gw|Ux0 z7bS~)*pe=e(4=CGmt;(mw%%C!To z9Ojt!J<|wq`c>tAgncUDNnbFIBe=rCLAxaeWGY{j6by`*TD0(0 z#Rt8UAUSvsi4O{I!6*#HS7Jsg8b9t)s6Rr35nGHPMLeH=+rSW{ER*80RlxQ0s!4|W z4HX*@$7DmeW3&h1HdfN=8D3}K877apIr#_K+i5nDW$dOg)&8f7(j>i$@eQqP$TW{+ zNH?)`@F+7X9Eb~k)yd&7cUaA-T1G_+vf8dmyNrXxCpylKv7_$e48j>;gn<8ELu1Ox z0^=DAi>P_m!VA55Vct41MrbS#)!)SsR&#(Zq`~UnlLB>7{ddp*smwEz@*98Ao3Cu-)Xbbr4wWTAL#jk#!kN zU8-{TDLxJH;ok4^+QH^72l&5~t6R6s*6!28`={n61=P#O-#vf&;&t)l(d$RWtJmLt z_xSa9-#(={{o+!u^)<9B9a)JQJ%wTOC&L|;5*q@3`P7#|DT2YR#g?}d;pKfexnl*1 z;9XETg!2%usOx$y6`D=W0HN@B>uSC-vVT6IcaRL5gdi`{`as>b(L zarLxvR0)=N24LkfYA$?3lu_`vK}M&D)#-3)k)7IbX||nnStMST}K<-0H8rU87=3L$8^p(X}$HGUR#t!_3| znSl2qb{AjC=?xCIPBnuWdj2l%4R{c1+oa+MV`UdtdBC?deay4u434C`rnbGp)n26z z4mVgkK#xFtB)_by9Y<6gnxR3h2I#iL^_Jmv9Y4&)G_;TG$j04%h z+A$$A(sMp|W?PGIY^)ZH)KuZavw0&$FN)f|I{q%SLO29&w#!lR5F#bimy^-vH2gK` zO?Ym@o}g(D4iP>PUD()j=c{L{mwZ0puIUFUoG};lbdN=~-dysKBt{5@4rav-dX4it zg&|)b@$BB-a?d3HG^_>D8wbQeB?Tj`$mcP6^zpJp&;hXpu4lz}@?W%qysxzjNbpc! zfk<;y$0oHYZ3DbA)s!Q2fr|v4wf-AusRmswBfP%SC*>Jb1jOgStL@AFC+pD*Q(ya^ zmYa9#dmm$N0A50g-?V*UAC)x&hiB<67KyQtMKorb$}i74^-vJc=CvKF#| zHP(Z8RsC3|WhLx|d0a0Ho_r_HHNXm{;eVm2A;JbVF zZNS*OM6Nx~5M}z;Yk39}G$=M~QM5qx_>$i285d`#WhjO4(^+_a)vkXwJDc`kV6|4S z^%?Y~R$g%OAyv|gd7V}I?aYc-TeRFZrpJVHQg)y;i3awk0sJ^XQ4%nC4a?l2QLPrV zSg=y6rQ+*s#sEBJ4o$04Bn3r3UC}g1(@w-~(9V4{XRr8)^rt&d+QyOi(;(wC5unEp zZ(NnV;@(@=U94s2G>=6ac=?@tDmRf)-4s5@-k^6gX3k*qt~j5%XPC6haGwa(kjoj2 z@{WO0&?*Gip+pBXf(RF^b=ZlpMRHeRnLSzsW7H*Qy;PM(4V@?nfk) zXN#_=Z8WiF^4A8bJ^Hv3>S zf|6q34_7cwN{|m~^GNK2F#dybs6x1A*M30M_f#J*9(Ha8ln(m%UQBTN@@Pz;3YxhN zeh#BESq(Q4@r3oWvLo&>ZS(^ z79|G@NG)5RA|$OU1r#Z)=wxbInS~uWYft;A2qM|Ly~gs^aKQ=NvruuiJ9Y_&lx z`jWl@6RC5hPoD7&vP#cbF~@ou?=lSNi9b&!Z&vuL3)(4`w{EQxD|XCsaK5@N&opQg z-jrdo>R_PLAnN#FX0L8Unn|e+PcueHDnH`cOeMPwc^PfqBV?f};_SiY_-pbMu?eTz zdO?vpQR3_y&b3M%kaJ0l0LWkHX-D`R9;VX6Zq^Q}LC~e=lI~IkmJZPDC*CVpUX8Vu z7z@Pu;43;=FIk{aJYJ{rfwKKKz`(4xgjml1kTGjezt-rRNif>R~J`3i%6f4_(>NKq;wA#21G#o{znTJspBzvx9f>L z^FAgKb9iiZ1nnw%?VHG-bhlR@|0oJLA?oF+?>t!=O<1hX88aOgV-3B$kX-`c+Jyap z06swdl}5)U{zr(TS{FySvH>(y?P!5iU#^;b@YUfUmqY^&} zC%q?v;u0lfUbgnrk@J&~AtPf^Jz4I|xP>^%8+nqmz)ju%_0`K4dlIWw-3PG@XTtVh znbRGz0q80-Y55?32^(oL4w` z?ln-YsH(NmtWD7DajXTZbdmK|In&039pj&U%TpWrwV8Rh^ke5C&ndE4ud4+#SC6|z z)!x;5&u6`+b*|6miq>qM?egl{^OV^JvS!1t2i!|oeG&sBLakXiXOD0HJ9UHcKNhzp zzrAhF8@7=?$!}Sm!Q{uMZ|=TDcnpbW;ae8r;M0<8@&+BhjpXLfgKjHsn`O4r&l$nh z{mY9NF6Jc9;Y|j8x`}L7^Hb@569T8N=(W5;98YF;i}9rvnhSu^MNLsm(iPttt4e-U z_C!2n1bDV*@CWzUaK^9CPST_WYCu6o6KIvoIdfAWLM_YcVoviCW2Q3w)bbpXlOu~L zGSC*!%)wE6E^uUlFJg@eu`r=BdGT?nA+Uf8dyCQiQIhsk1B%t&NGch5OpRBcA9qu? zax~wz4_x`Oeo7A-9j!gPq$OPFF*7Hfc*;aZky%{o&X+ z%ZOWdJm0VqPO`mxkvw2dIYX^L!z|*%FlxCv6vAl7Kcl}KmtpgyiuL2@)R!>Dsv9c8 za&&xMNh*vdz1+><5phK5&(bmVTB*Sse3-GKnHsW7KkKQ6n<5uvus4CuT@y8X%hJ7W z313G9^Usq%naH317T-RK_2f6tcsUaOMW$qX|3OiH!6zAot?DSJj37~hrNDBAFSuHCK@{wRFQisNrp$=j65vYd*-{QX9zr#-{ z(jfq_!8X+$zm;i@25t!XpfEkC{zY~@-fy>!r~x$r#WzhZ7H-b4&@RtI?!CFWbuteY zJHw(0sRPpTxgS|R_w(4UCpwKuyr&o?W=xQdM zctMJfU9rSm#0)R{R|fo7(Un=}4t3&ZCtQB&b!S5spQgr=zNy6JnUSLjr*ac}#w7pr z`FC~dlm!+sU#ykOB)}u&<&&otmIArAdPyV7?p9g&Yq_aTm@G5ZZlV_jED{Vo*?cTu zj+lq(r@qi!B2ln8CGhck$sCe!3CZ*c+@<7K-Ixqxl{9+qn^9n3yAP#*47;)W>6}-F z9NjKglh+B~7F7SSM3MD^2Z+3G*k0M@E#UgvH%Uj*6j&tcr zr3hNI+xQHL&BD?^Y2V1dc>2}Pvr8YmBF5+=`ST7A{k)#m_BZnBeU*1|0GB$`xYT47 zrcHYSv*{_&XCfDxJ~dwt#G9J@m}OC;q%}U?lEdQmM$`MxSB+dK*n#zJrj}A2Ly*v4 z9R7C;?R`-&U6cT&&9jyR+1G&1%;MbnLLw%$+A`k6I$UeWc34zf+h5h#OenKjNWZaE z(_wOtKqaBisBJRBaUDw3jni3MD*SUgOOQMm28vD%RQ&W{S)9TRMIBS6T;wqdv?f1< z%HqZ#fVJLz4eBVcV_8!~|9^nou024DKOv&p0}GEO5t`4UVpj@FlLJ$$^0BL@D`AEa zmrDmw*2Toiq?`v)@1v=XmDbmm0Jo;DyGq;rilajunR_ml-QSp-)|5!5so65-*o97K zc-=e}iPh++qN3u$XX?hnc*%NW=7?`V^f1Q0UqX)LM2YEV;;9~G(_&A6^KbAX{*BQm zReVan;h%k)eLJ_`9^E`JaJ&f+O)N-Et_L&RP!E6Z$57A-lUs$ifAb*tGrx80c85>5 zAU~b<$YHAIW{Yym&!C&F6E{^TBL4Vm=lS7S9Gw9FVL!D_28h*w&OLE(@poxy4<{gh zcUDoctyXolD9x_r?U8m~oj#CLVlfSe;X9u!J1?(mD;s!F!(Zg@odEDaiN-tB-}}Wq z?zLTJoYkP3!Q=kvqS~4xo0&ux0=3V#EI@TyoMm0hP1f1etP_lj8<=@K=7QlqC?YmK zXGF(bi9cdP*xZJnd^xW@7gUINKIq^{JreWNuW(MRD_{SRWb8dYxDbTHM^@9MYje-Qg0bh9V0`9RYm~99V8lZ@(b*r3 z*zCRU_!X`>cE8-%Ik5mqGqzHqQa^r&%$2 zcVwRNtj{;c*jq5#uuAcw2$BEdYusYrhP5GBeNsBukd@h#U=DgNEH@=XK%dtoG6WOx z_65}OcC+03ui^slyLF>kmE~e7bklc>F5uQA(ug-0_6m=;860!}t(`uTV4dzW2|rIV zUh{T>v&n+a#k7#(hJR(@?Z95Is6gEW=PYyV7`_4vE+Ngq5D^$9%0Cy`J)8>pu`rLA zGZY;rq3x;9IfmVIjoA8%yE&-xW3q30QYty!0%9Mj#UWYF7Dtkg(ovtl_}+F7rxr3? zgw&AdXK>Gl*sJxSgT7*7%pg_o*Jr`h7@sDYUXI zx8e0q`s^k%**u(RJE=5EpSShd|VtmeVuPQNv23t?@S;WCJ9(_et%^p{=g(m zTd&Wo9Ra_`)j%dBj=<+bN@ICZ_$Dip0|{$r__RRJ3(u-9WSKp{{_Hk&&edtt~~ChK3Zz*u0rOgIVJYb&btTx$m!a%2Sj|2M@0EM zUAtT-m@F=BR5&nvrQat_&Ddb}Q`eDGqOReAR~?icOmjuYj^>3$&DUHphz{&{Rn6${ zO?1Q~q{0ZU60*J8(7|w`lHrkITyy{ej+9+gc=MUY&eXE24{OG(e;7d>q>gx<*Da^> zv(Bpu%ekRsGW>K1wovOpq_+gxcj^Jf2>;rKo<;pF_zm^r;iLayhBs-s5Y@U*MBN&xz%A~8kpNdbKBIvd>Kbg?iNhiTHS7N zHOI%SjJf}tOmBYll$4}EahMrX`Y{8>G`YkjSUWj>%&CpGSA=h-S9adh2B2xqd#|mW+ns22+&6fP7Z6=$cic@xqog) zL};t)TKNEQ)KnN56^BJvH5ob0j7=EABJG!Su-;T&N%PuSH_hq59dV;T#jnlpomDda z<%dC}eVSTJgK1&hZ3xiAt9t;B8NG21T=U17Vf_R5g$8|RtORU z)e3Li{O<^$AA6Yq@%h(10cvJ-^U^0k;G!$$E^^WaT(d9=3O! z>iCpg3V2<&CI0K~Z(#-$6mN%2>X2u8U4fx4%K4J&qkt_pA;!=iO~4CXV5zDYEs#*6 zsV%~%(@rPEgf$vSKYWam?yFh?0~VU}%FBF9%LObxrhPqCs9$fYvc_2Ez6b3C7A2%=20pCE^Zc;e5+~= zuv0ENoyj+X;YEn;fq(KgK8AIYajJ)rfcmZmUIc(BTjEc&cd@|@RxKkqW!enDiS5IB znB&a|g4>48aIIlFak+?KTQq>mFR?apObwm+j7wAuf(R~eau0pVCtCzVdwA?HW*g=! zwDT2W2re(<5Qcb>QUAiE_H$zY%e&BEFsdICbQFiI)OljJ{-6qumBmuuU)xfA;ggWO z>Nw5&QOr{Qh8=5wAGbA3LEude=4EG5DUw?QrBhxE2uDdL0Ni zkW3guJ3?G2V2t>Kqx5kF?IMinbKeg>J6U}eU-&{9G)QqVd3*N2 zI%UEk9~jpg1xU#u%RuMj6=#9w7{C(%8ac@k{b(F-X6m1>23zn=!M0k;0hq~t;W`YF zmYQ(Fq#s?>lQc|g0i>qdU|&vdva~f|uy>u7*YM1e z9_;k2Kz&w=RA*0Ge9+aASWYd8m>Vsr?;$lD?z=cm`cEuCN3Alf=uH@__}VoaKilLe z7&i&y*FMh1z_ku4Te9^&U;%*M|*9+yU0aK`fkg)(+TgI^{YjdGF6HJ*>5MKmS zP3JLhS`Y?4vRA2LUEX8d->sY!@U*v_uNqJH_sX1drCO1Vn_QuFbc{#Fu5fdOit$Yj zv4kcPZ(4EBRX50P%7Ey(4N3fN9hN6S*jrwF#BbF&IEuD~mP?T~(RiQKX?S^G)?xVu zV--Ot27Iy(=gAm%lhp_XRZah~`;#`E<5md6CYWhUT}zi&Wl4PAZ?|Xrw{Od<=<3H6 zXtX&hKa{i8^7hek{q8o745v&XjDGh(uG#zT=`xiKUzhWf$KWok1}ZX{m}1Nei;B&H zwB?*4b1)hYqH2LPGT5Qi52)c5+O!kj(0v> zdatVgvZ2^w+1SY%Qpk>mSWt}88YQ*_3V1y_V8TxjRPW||ds8M`O%U`KHyxYO@m!cl z57GTI*5{~?Rwe$$`@j{6U#1jKgI^HlOljMy0{oyf-6Q!e>7&Qs>N^VhXzueCkj84o zaKj^K`Y>cw<%GlUQunKJDZ<38$mMc=h9h86pW?_uVb;lJDJY(h>RR8BT#M56LAIo) z)+}uH{6009I^>>()PyD+ubxVK`2cp4bK!R$w`v8#bD04`iW7e(KkRUgDJ9o5n6hDx zgDmlNnc2nTM1uaXL1O0H3GNl-=tvU9U#_y$qy_MrQernb@w1%`lcxu_2RPQQk>PBv zH)hh9TMP+{N-r!)@tZtI-D&q_XqTV-tLtwbXToSG$>N)D-%eO3f6e2y^Mgd>e-YLI zg}wygUoM1PyU2a5D_``_DCOzPAQKhU#ogq-0vbG&OAXUsD}dPHEqt08aqKn)d`}ow z3LJ;Hje?^IeH>)BkAba^z)0v{b7LVwIPS`+2i~Gx2ohpn%Za zNg$qpXwTF%KUK|*n747O;@;=F8!@gSN~IQEFk?zvyHSTj0S~x3K*PGCQ{4wpgnV&q zs%gFv0VDm2M|I4}ag3vE)CVV%9<9iD?3<<2(G%=f(-B&VkEK()9kdp)R9gAn?0Ra8 zTmQd&rTf+Gh~bd_KUP=Ky}{}WS!L#bQ*n3bRFaTWM)Ss}2tTzi-H_GGrIns{GW2bV3_?C+L{8%8= z4Um($fUmb{xAZ$YZ8HBI_L1pdAzE(9f0V>7=gS(hAwoF_1^0VEnfGC~e+W1MkV**K z8kFD#96$>L3o``72X-3F-*jiw(D&B3@7po~?M*JweH>PA;uq=h*ze{{e*7rv4+yz+T+a0c`^*2sU%J&uaGo z^FOcO8w&$gd2j^0s1|a~!+ll^(Z?SIVi{i3sZ(9K=sc<7#Tb-&(i3pL4`9p_PgAPt zOcp+EisvJjmD)!z0TAdAu0qmoCL6=ci`6&0uDC>TXVTd58~O0IjYl7T_R!AR9Ozpu z|21}n6}^k_&w(0p3?WRiKtA8Mk+m`;iOb_uZFbH5Rz&k6vF6R1Np*LDu?D{QyE^rm z^>=jP40hqtU|gAi^dghL_<|`(bhYb84yXS_?c)OoQZ6olB|$uJvz@=?V7W|-ZCIeu1uRV^0fYOGjto>bHfbCTtrTZQ-C-JOA) ztGBGgWBMbfj^4X-nZ@S{jv?DA$8e6Pi9~T682N}EanGxdvJ1B?HA(H?yJ76y8h;>d zA8p&atm1y_U5k@-BpBbdzh0j~&e4Ng%j{NS zc3x8P;U!0Owl@4O(E9m0;aK9cv+S`FQ3>djX@i78uzyVuM$>^i*z6{&Ty#mxlf9d4 zUQ9h&ETWJie$!&m6RLQqh5M-=Q-6Ma!fTy~p8oCi^GDzQ+tY7f(Ff%5ri6Pe9exlN z|FyWlF>9+l_*}0)piG@?X2qid-=8xpd8IDFiV=fD%~!B$=)F0$$@PZrDf7^Wb=&Rt zlLlKvKbrTl1@eNsF2+gdet3G))`JVuMTM-QYH5{r;1|RhlRsHT zAaqO<8v@)c7<7XLdD zcx?n%8*d+Vm_s4m=EL`a=T<4;DPc8FUHSKR?GK32dKUw}wX~2u-3Ecn7_BlMEP0js{f1YvlxP;X z-`Fi2Owa(NYL$W1f!HOKwB&7nOV1u+0t1rL;iM`gDBC5hSIbz#oa<0UDVNo;K=-Dg z)w9i6$e;BTqZFU~n`#%r3H*yc207S2xZuNiX=z^2rz|b+FH-Le|K6Hy`(Iq^`16mh zeXWSnfv=W-eC=yy-(UYcG$~-!8!f-|&Cz7wp{_KYV$twLh5_v6#k`5@6Z;0=bbDaF zl!%cHT@jITpG;H>*6^~xXFlYS*zxXeIyiSoZ&+$cq~ytLMWR9FHzGiE*IA~J`!Keh z)Cm41G-ms#P8BuPMOUe7H#0RtnQRo{MvYoWE%*o;)5-jNDV1MUi&B;Kvw2N*9lL=v zug}Wk>O>~6mP&-Ow^!UL#&C|GOp#k?jLdHGrz~*!u?fei8E-#@fABOIIvaRHpD;3@ zdDQAP%$h3k#XR+D-^`^MeS7$cF!U|USPvMQh;Au|mGJWKEPYQ|Y%kSs|u?N;QB8Mxmz! z^-&DTG@*yyjd>@9K}vVSjv$6`>qSj~=ViAY0$Am$*V}B`s`syg46AwcY=yziTCH;$ ziGqiCIh{cd#ln!yW_`{#B*yz7hUi$h74l2X=a5^8V!d~l84=nITajk1VdJ_rfCDP- ze2!0ZXO4_f+AR}(6>jthvO=p1YLz5RD!h`U3dV+@qq2NtCpVgIx@J(D-J1x=Xz;w8 z!(kCJ{PA2IMFb8jx15yAXnY-eRX*g3*77$9oTgOQOl@gyp_wa`^g_$|GO*a)jTj&n zgf|HCl7wZQwc3;#q;|gb;J04=Kd(;o-8!Vv@ec+U+I+he4&a>ho2@xHUQe^CmR%XV zlulO@c_5wc^%;FHIN?ML>nwVf^j6^bdIHYI>ff#2cOedbv!O%)w_mGk$IhDg^D4S7 z$}C;`-v#N&+b<3C^V;{SM(F=7pMKKYI;;nd z9$QKpp+zmmv~#KQ09!z$zY?#3Qqvc9F9vN;qu`ikPZuqD5_~>rRfZ*6^kl(v8RMjn zwO_)cffSj8VF4uOFiyXlLyKP{Dy}H#+E{y;%yb5OGw27%?(Ia{aemmG2%Bi~q6`Cr zvTGupa^wA_VN&BrP;1cW>keg$@#^=A5JtZ{h(%fhB{9u^aRNy za28nMpi-WmZ7(C6oUf2sf*U4I7*E63swNaeJ6kbIipXkhvzeREgz$oH zJ>_!y&3FWbRkocsJ!rm_?dh@9ea?5h>VVPR1IYVac+b~z#Ci(hp%dEQJyI$@+HN}@?crB4`})fLY#)fa(s%}8jtwgQ(zhvVmp6ran{_0lpi$= zz^ae-by-FP8Iyf7#O}C8)dUhmGnc$+_t0rJ1l35T*GLhKp}eO|@#O9k&NsTB`7Xr4bY8%-F&_zSw;-FwC`uCTW){UaW5*=O!=S)t;&kSNBN~MIP*Eb?FjU&XKzzsX z3#Pkc)}96qHH9kM&<&52gvuTnw+iH>M5Aj#5(psc%-C||EWT*CGPbgy7Iuk=& z-OYoiCbPORzOTbIB4l%2%356n)7LICBXUX{(zOG!<{c{Xv#~?uRlCQ%T!mcuCTFTn zPj51^ zw+(qyfc5NQNwQ|Vw#hsrUp@Nv=@aj(^Qfrp@u_hRIc*$Id;(a+o6)F$P(jO66D{ae zPQ-fzv`3SBFvP=G3R_i#Dw>=;oU`5}b?X5~qU0mG zKnLJp`?;HAY-@qPtNI)N%Fr%4zh|UVg6tyAKob+M&4RRpB=oV5!R&0uHno{9g^jVG z9%|HMpFt&5AW`FIn`LHVx#85?KpJVN=vI`ag$n>@C=xmhxX>C<<1yjkKm zb=tD6zvLC9C4e;HRilM-`g-lF**m`&8#;iTqJdS~HP|c0FMv91-nLPqs4(mPo;9Yq zuHhqDL`^^T?E_2NZHx7-=4Xv zW@2{zrN=3@R|wVxR;H-q|0*ShL-2D9ja%58f!Z~h4Y%x9&?K~hh%^+xV@Jo# zfps`)v`41U(pKYXUf<{Ii9L|Z`#49o>kQ-NSu;NTFyF`mpkecu`9`i_GxN82=xnx2 zJgnfqVvJmFHzU&!5$;z}uk-P0!H)eg{rQDZOi+Im52dz2-A+({Qs4N6upkZWkN?J< z+9hHp)c(2gX{(}IEeIv?#*V{;M_)vJ07c#)J^CQ`Wm|^ThE|@@f*oS%X zu%Ht(e(*}%glKZnncA2`9JP=1`sq;|^U+*gNYFGAlBKi{i{#_xxsZ9CXnBOjPXm4U z5TsBarOyprDBDoSn=*+l*_jW#;aS()cCnP2Nnu_s@yv$4XL=h5veG^|iTf`n4bFjo zoiESr;IwGmh*$4VRkzW(>qhKc&2_219fi2NpG{+9*KQ{5$JvkTYNfDXaI_l)917NA z+DK_$>wqCOo(FP^2U#3Eld&WtMx1NziX50vUs-78$o`SzJ*Q8Z9iX|pH1w9w5y^(T zB#A^lmuIHuUQS6eYQG_K)qXHHwRd&20k}|lsq?m~IFHxz%B$8ILN0gXwB!CI^yuBa z0Hzs?$suI<*cOj-S%r*4s~RYXjFpr0DaC&tc55N~5HCR^b<(^>tk#c$;Z82c?l82- zY$(}U554IyVI7wQv)&G z#H-q_MSS)IB9OFJOD>PZi{SU}kzlz&!gS#uGW8AYui;KQZz&x>Fg!Da@BWS{lUCr>l z=MJ(3z$8LB5Uh~}BFDHQGr)m$?g*Y7#aX2b>n7VFvJUjX6hkmXy zx%pF-W_?ZmeY&&v?@s-41}Asa(GD=3 zcVyG0c%dOCcA9DjiHNJo?E*SR_arTqoW0LPX4+4kz@KknP-l;0Xr=h_lwu0(7zaRAJb)HdSZ)n@d=bsmUitY9rb>D;4zhDWV zvOxA{u#~To=c%eDg<|UPUJJ6RdS%K1u!-~E?YF=(H3|=E8mCgLMF`1m3!m#DwkPCt zu(-2G5gY-;$eCq-G1yJ%!J?~3u3rOfTDCp%zg90Ch3|zk{}hJ{+^ZSMYm0?Dm08?f zwR}pgK>grsu|NJBkQSKcK2LK_+0xEKdwfx0*3`0#9&Y_<$}dhOOS7Uc=HK;_&zyU- z7Q~H9w9OYL_}c69mycuw$mzp`@MQ=G)`SEY!hWMVL##hQtN$UH&Z$?!CBdA5wWb>mGfg^F$HK_PS?|PTxk{Cn`<2cCcMIa zl-RRfxu-#JqeRR)R|;v(53V}34ddeFXEkm0E~1*ILZ~}*)RM6@P>k~s>Gy*A)FnO1 zoeA0TiYfGhLw|B@?*~`WrgCc&N#6WSriP(+X~bHSUhb}Y@HK^Fz<4s>&ht|06PUfA zK%nUI1JHg$g?J!W8>Mxmwt^)GiB&SNEKUA$zTK7^x*X>1wC_UAXHTZsN6!7t64#Qs z%VDz-+YQHDb{_HgI%6vv>%bR7Bc*Fo`f5Wl6_u5^c5}&uLg;{19iDwhSJzbX`X1Az z%Eg+=sR88puaU5%_zSS#Mi5B@wXH9px^TjAxG=E>L=nr$_N<(??bl;lx zjl!LJ8!!o_0W%%^m9xY8K6Y1i(1Sb&d%f7AE z^tY*U^v+h`FZ20A-hJB&@pm`;Rjj~YeLI@Q>nFScaiWp$FX%INysWR5+qMmv6!hS& zn*Irw*kg2jrCdMTz#qy01JwekNIrpPz9XviyAYx*)B+7%9fwe?Gm0b~^|AFEpwp3W zZ8>(;CFQG&KMRnr%X&Ko4QE^YWdQcEGOc$G+CbO0WLWb5ZV`h|+h6ERm}QFpKT||J z7%`$aG_%lU8Tr2R%qpMMPP}<8!{;nxm@w2pQWVSW@%s)F`utxvOl0Z|&Yri}A*}?A zQe83a8-F2DtVwk0M?@qw-=YOE5g5QL7Kkp#j@X7^F=t_-ijg!hz@+8`Eq;O4mF6|c zt%?3jC#IVelvx?BW$(hYSZL4glY4W?-<^lI1gme$3^*;a{^b3GF;CO3=lEwHVfrXp zjByJ4d9Y=q=5w1t!r*L5nSHeX60@AkF?w4kc4!;WXy2j}qX=PIUIQofL3-GE!&=04 z=DgX)6iT4_&_uCGCl=K{*IWCUFM)fZ@l#vX1zYNE$DTRm`^&>+QsN8EK|)z-^h-7hd47 z#kHt!>717}ka=<)M*k{9YFj*B+f;|VEAJN#_H|8qhkl0JD1LX&DN3{J&f9Z+MK{2ZGLgmg(U z!IZwNzy8a;Y4=gKZ>3akewo+#Cb*t||E>kT7Ibm{Oy1T@ooDP9|Cn33ub)PR3qkj! zJd=qbbpHW;SvAUJUYpUiCwWwp$!k|Up;TB(j7?xN{0sc=DN)B2W(=K8_{TQ>xQexIpo2_h> z-dII$sRjm_4-gRRdks5-Pab$42 zsDtO+$Dw9@9Z6@_ZTewMojav;6za~w<+&_Y1B)g7Z#XIQoqJt~qL6}M*#MB^(*#8H zj5R|th2wg=NjG`B&Gab5QlH+oX~ll6!}j#(e7i<(DT$2gY)5Izhev80*GKA6C?K6p`-jT2JrDxHGDtpZprzFP(uNPb~`t^hZ8fVz3upc<%1`1 zWJ%_qLBHMK!~ogfFfhn`SbP|{N3KBT!!4!%oEUL z8kwJLH8c>e4afg-_wPBh*a{OF#bT-`z=#n&s8k3n>wa`vEg$ax|?H!q(-JDbA| zaZR7Rd>-uUA&PH_+bE*%h_VSoxhgps!v21hvJ@8S~8}p*7)4xp+R9TpJR?fx@Ppj zISQ$qnWg!7UL(l~<8)l&ZRBQt9Cp$eo(fP9B#4(P!Z9}c3Gs$a6MvXwIv15}3>UL6 zr5JdYn@(Y>p<#Vm2;H{`@|kn0fA%}C}IZKhbL0iPME-m54W{YN(*?NTmNzIs4rax(#0S^6- z@d_Ilo3a)TcZ%fgH~;u}=gyw|=TGu~rTlUCUXOb^f zSl#!2>lUX}Xpr{c?xq;mJH4IizR`7_1H0$5pJB(78GDDZLIjYc;h|fT0JRD3@u0KNdm&&eF?po~1~&C@=i0p#<$MYxs*}kHBAYSx&k!uM@?jP3l@{A9kVit+#b53@V7dy_)W4$vfF zk1topmpEtC0|n2H6uC^^1Ko0=0-7e8jr0-;>&bvwe+FE_`mX~5sj^s|zGDKl z@kst`0{7~FN1A$D&b!q|ku}8di6e1}ydi32wiuP7aPlE&jvr zr{CUL{^jM9<@-nfw?|(*!v7wB_4yZ%p8ngTM^7Jp9STtXRQ`GP__h4|^5XDtlpG6@ z)yP=4*(p4ma36ucHGe7N{`#c^*T^%WOdzS`@2ZxIu{7gm@+F=)HHRGxdED zl1+_!yPw*I1p1`tX?M%kE?qy?_D>nU^%>|IACpvpiCRVi9F@U-gk4PjA`BXnjra{Kgjt8{%xFJ!Z_}uMRLT0YU@nP z2Ym!vuIsWcpq`Ux7xUFNsB)4F*GLgQc?WXI`X>vuf;15#p>V0*x)q+1t!Q<^_slNgA z(K3DpJlp5JJE%WDtG`|!f6y|(cv>GfKR>&NK8O#x1=K%uO z9VY;j_?ZRpCv>jv7=ZyuQ*_mR|@9kW(=yN;4Ec@fVbh23ZndKW6SxTie&2D)n!)gP99hDn@U`;e*Y)fzmuXr{{cm>LMD=N)r!SO%d_|M zqjFmvv$v!>8kGL?|Ym&fv{?e9yKv3h6=a9yLOl?U6F$L>Y@U__zJi_LuUSvNFCc$|bOW zbP^@Ek@ThlPiajJ%Jsdg>T!R-HyVHND*@1au3+8S!lyt#b0d*YVphYUN=|jpLM5%h zRe~DZ^}Bb=636n3O%<0XHVJ&Kg$0dG)hw&^whTF8Xq^vsrqv?&i0QR6LV}&nSInmo zOiHDEmhz)Zo`srW&0zQ1gfMdj^PIqk@_4>#8lZ<$skHjAk|~H#2}3~ZWhj&4<3JUe z@$9&{8CHhm4!ZX!jICVK7>6;(Pfwc3D48cZ`S!o?jZv%YG{kR=HDz1;y|=VwOR-D@ zu1r3YoB0)g+i!kl#7};CB%j-r_!lt?pW$cn9ShJ_unQ7;1_7jt$$n;izX}Q7F?;BP z+@93q(z2DfwrrhO_za#)O20%Y7%(aQipJ=Nw*B_JOM>t4EeW*dJ7%RMPMVpF%vaH8m)rM3*LUwxCy48IS^u?^JEc$- zE)XF*ZkMO?<9e?SiKmaM5XY>Z(jS4#Z!61jzF8nM{PX#-U4NnJWoPky>4d&zllG(I z&~FA=|ApgwrG)nOz4!z3GAVLtzBvSav}vo+ib_B)D|8g84gW6`!4 zjBSgLZt-AFN6sOyI@v>B384 z{o;hM`7|Vh`H4(#>;Jv4&)PY z5KJZT+eL7idm7A)qwiMYc)NbLlIdT7memQeq+&kz5yA&W!@(e5NRBU@fn|iyv z4Bo@xmZ~n~PE#(7e-sJP9FfL&A9*py`%wgG7F+63CF|#M0v%3tIz7VyLwFSzH4}vv zC*@o)QZM6W^`VUGlo2j*;yab)UG3GvSn^r0iYnqva*>7(;V`DxXPEW4))&nvrT_#S zR!x@HIv})OE}DTfHw2J+1QR^7e={UOAbZ9H%?U`}p#8VY-7Hl>ba>gOtvHh`lK>(0 z%Zt@F8`z^ImR{4yxS%oT{0h;}M;aAg*e-1;-^HW>;m~V6>FqPBhwEFCxqQnYzK7bG_rIh9 z%O@TTKQBC>X0S%irNZ@P5b)+{%yvz~H|f*Y9IukzaAV*rgSR915XjG_1LS8ma$e3g z+5^gFgeYqsd#^+XF4Z2RRIC$PuTwEU^>`elE-=qkyTVQl7cbl_)8X$JnH`}(+(ewJ zo3;iBfi0Pv@7ehVMgVvvaw!#-80oHD)!HM5ZXz9%JQS6hb}oFjY2IbAux!7*ng|6m z`H2e=u5YV3p*e3!;qJ*2DuhV^^)Oq+D?ld|V2;)y1O&#YKcyonwz>ewjtRbq%|XR1 z;ZR@Rpg>m0dSa~`4QAI=V8#t>1ip~k%CJ5oeId~200GrxzxX3t?-z%ci zXrw8dD|e1PSETNg?WoAWU_7~EkHv3B$6{I=F`}xEHfe`rmQP$8323{4prVb87P;{+ zVv~4}dCPSOO405fud_u`)rF4XvndY`^P1Iy7lP(kr&BRrElQy>4_d)}#H36gKNbOU zTFQm%t!eS)m&IrJm;TIhK|8y9Yhs?Uc^WDS3EVM8`^odfu4~-M2D9}Wm5DHoOiLx2 zT2kc0+hQNzBR76kF3;#%NYzLh&=qD?&Nn=xMF(@_IXtiFJSEp(^xva=K2rPClweAp zujH0YNWF>J&v6Fq@Gv z)>jzYHET8jZN#hU9frP^JISS(%;az7B{mSGKP9mkv&sJ(acV|1jyamzy_ToqF;Hp% z@j21in5}0FL9(p3q0VFmH|hI=g5UfZO%qEL?at)sLU&6CSgqFpHoXYk6l`I?3f!dW zF0mQdJEw+jlms|2YaM3TDgA{PHAMbW4A7`uXbF>g8GQTShlQ=rFaSXscT-NBd{mmSiGi{=Mu zn@9jKk1E>f1`@Hsc@U2~*({+G#)L4$^AinaeZ>2Q9+C^)UY>*)q)bT;S8VVU0LuA* zf4o?mp>XYJ?R1IjVX%uV__u1;z zb}jDcWkA6|KvEb0m6;V6bNswJNt@T=K=c8IDi5cZptd!pmoB80aE-hw;gv%nK^)}E zxx}Wyt2nHJ%Mkf-CHzVY-dVWZT~xGUPo`_BV_G?`<4>a|iF$uc|3qyH)4v%1BU(XZ{ZKLpqtyUNv{9?mpG|pKvC_S-o zPbu^r^jDcAQ7-dp1E#urS~PK$L4u_-yd#$w=O`Ph*x5Mnr0WEj2uPWRQLJ!c8!q( zw0}OTOY|@w_|#XGt`1Cz~s_N`H}qZw&wIHs%(1tmP{mBvq7m zjQlo}ZaY++()Vy@2qYW>wFj{o0u{ zu(9tjqYqI?k^!9UnKKl(2J=&x!1y8r#dT|N>-}yeGZ&W$tpfBy3!#=b#U_&Ms67+Y z%!RZ`Gg_>w9^NA@9j0g_(pF-O3%2cQIkcE zq_e;v(hudI3I{g0-`AkD7ZOG`-0PDKLd5_Rj>c^X#RK&`>T^~-y^eP7cD-&8kDfDA zZbR15;6>46=-?1gc2Io5Z}f1MSp37g{$(kiSZYSWD39?_Y-Ln<9_l$rF#sLEf41V@ z3|d?9;J=Q!D^UJS{Ty+6jQEi^VHP4wgq8aE&I^=Y+V>F_{7g-2YBaUMbF0qTP>`I1 zxRE~KHWq*14`kH+J{I4?O7mw*zn$)Sf_&f=*cO7$)+$f>T)%52U^ z+O3OI7i;hRRDO#4wAaiqA_7Fb>9-Hnp#i6e_m2D*4kKB{2kknZ@AK9{IEoQG&9Qq( z0-2?`!OF=jL7JL|7NXr{1d`J{r0k$8c#d{Jcm*qUKf?I*7&93)zJ79h9yIfXskOKh zsNHyOs78q&+Gmf#ZiYNW$rjN&f)oa8j>4pD|F+L=O}HUPW>07@>E%V;i#4M?Zr9*4 zQqyI0WDE1e22&!8BNA+HS=Lg-U`jM&;5p5aR4F$ykEf#e2KOyq7;yWWHoj!MR*+h_ zsff;8z=6U=dsJ8M=)k?-{z>gFeLQ5-Dcdi+V{oj<$F{Z#0u?j?CPoaP1ZShP93hmX z6qx+55UUGstkN*6>fmnh(ISt?@SR9(%sYfmh(Z?5%8++;;;l8pQ6~42nz`8sgJ2RS z%eu}AVJg!&EA_zr9U#Sh&`v)iFTZ!U2d(uhYV$NM_C$?(mRez9&5UN%~>Y zwR$mXgzEvtZZIs}eKZn*YJ9acUmBoZX^MO~Wy>_2?=5K5Ba>phn%Dcq-F{w9;|AEF zxlh0T_z2kz^4A|<${4Zi*B%i;{yOuuml=@T32f;v9+a2=IC|{91K3{whb8~dJQsnW zj%rR@F@^ubgQFbi`KBwzX)fGpYt#WShb2hXFZ zg;|(`Ai*(i{cB+csvMk*R+kUVbf5X#Y2W0zckc7f8V3YCzz&!K~ zbFU4;;Xt$a3dqBNF=&spEzg0@Foli&;X&_;bU)z003Pe)Ll(H_4hP;N&hlL`?}OdO z#xj80!U3qP(4KxqH8!ta(9aW!n8IB_&lg>Cw-G5EU=;3*^Z60719`OTa)Vf67Pyx6 z!}ci#M*rvs`)YmSL9^U}XZk(?Tf3C>=5c{b4Us4@^P?vBu<=G=As=5|@11~GsaQ|F z&d1%0*0s1)@ZlVHiE*EfG;Mrzri!kC!trZ5aFBSr8SAL_LI?jEn>p`xKQ*8bVWzVa zBgomQVWFEB&G3OFWAKF{=yH)>9b{O!-?UD>xIAvItj43rbf%5L88=g}F6MlkwY^ve zx7j+Vvf(`ovze_=7>2u6EN<3CI9e(QWLGGtR3n+1;2Z(g7xV#({M8+rntlqD|TS`f2t{TerKr|V5{okl#|k}c;)Ky14XZm<~$OqH{`3{$~d zyCU2w1u(hFbaY#-S9`1X`6l!&Pli}uA{kHams z%N{e(74EsO4gZ#dPeEkg?F9V6(&A-m(2};jU+zt&zOVQRKk&#W@}&w4AHyI*kdbjR zXc*N&`fv)F*#pXc1|tc5q=h{BJk|1ay909drYpk-^sY7Ww~cR+5|eHVzD|~^r0Z@u zh`4&WiDB3r3c#a}N&g|gbH87Y31u>HtI!E#YK{@^(1+|&AD!D#oh7;yT_88`$kGx!|NBmQ01Lb0i}mXJ zSJK7v`S!g8^81K@MbUFEHSt=P@rtc!{IzF`B#PZZJ-#O$0I(_g=>-3FE z-{i7FbddY@Tr_6Q+Cx{k3*^ZN@olziMtkVKf?qR@$rp5f!z8l7G^D6>u^sr-pH=K* z|43>56rJbZgn~3u;EhnmHa--C_ZHODl-Ss-^?6-{ouPP-(Us*Y#P5accYLxLsZf^; z$i|a{iR1KBRbFVqO-&C3()48uq$K}ljZ`2IeO9Mp1dl`8h@lqa(3q>1f1ZkHFf4^TS!F{Rv6C){G?EchfcJ+m@&Sx; z?-7lOC*-{r3_`AFkB_gHAOyjfX~bb9EhtWG*n7m*sL!hKt0cAg@WO;XDr6?tF-nKz zojLwMhg(bpMZ)P?J{QMJk!Hrn7D+B&mH*kCBAy^yAQzdPcyJifa>^LYjCUuU@Bk~B zCxLGE3;CX!f6}l`E&`#C`sJ6L>=!pRilGD0K_yAU<1I%@4;&cApWhkM;MuJMeOQ>` zU5!8{LF%Ri0=eAFo(g7`o~>5QeHiBBRxv`TJU4Bg&Xj7Ih0)iCgX<-SZL@2fRETf2lfIy8F(wty zV~KujqMbZmnUP!; zMjp*v(n1x>S#tdn8hJawmFpy^PFyH`>jV~T(*^M2L+0Fs-^5(Q(1|~X$FlQm|D0xv zgAb)V8^hIubQ!mvG;5xG3EmuBrZ#6Lv<$+fx6sQoX6}|x%%1pkiA^e>47)$sHEI3q zsf?+tW!DY1?;>0#)Vxh7Z^RKVU_*;wm0VVy4%_A>paS@@bF#WGS$R?0BEE2f8tlGtOVD zwMeUNBfe)d#HOKCM6B&)DIl3qU6~lt>}Z`F2DKX@qz>>;f5I>MQa_gXwqY_+FlHG3 z(nf%c(I3sq>oYA*I;t$snrU4>}Flp@8{Kq5&Ry>PFdm3ZD|s~L~_Q- zA?~;Tab%MpE2MuMHA1V$=kZt*(wea#@#SMQ{z@8~z1FEXuA((cu>)|B>y_~2Iy0oF z9XF*yq(1D`W6n67BSn3pP)9ZQsKj2VyEH4A%*h ziRgNwi`s|-|r&I0_|%d_tcRXk1p(2@ZXF2)q}Cv!!yBiGQ1i@CS=Z?I7eiqkZ* z#^fLjpaOD%f>JKNt(4nEO zm0}iwfvqU7>w3g}-(#TwGem(j{4-=)oZ#z#7`~D)0;4}KqSC>HsMFE!M~X4I?kfZt zJ(6hVwd_~0EOylhMmvr{G~3bfW_I+Ck9YpW6G4s?IrSsk*qu5p_oj-(lb7Fp@%7Wk zUq5^NZ$CVF`t_r~3w3^f=gxtC|3+r_F-!|K);C9`yNy~R*B`!0JN$Fd zmc~T=ri_iHn139^`;XX_3GW>;P;5$z(J&$;kHP0w&zK(s95qBIphQ$BG2W2kc*t)S zQ=^s<+iCdo$@*L_r$RxZo6%VFZFyGCw_}epPhjf{8Q`s8ypgj~qK$Q61G!F-(r7GT zQnHwZYo@l-+^%9{tJ!W4kjuKog@<1d=~crCO(X+3a?g#?Y5#t)40%Q6g#M_o1! z>1y@@IJq6hWzQU)huR_g%^v=ePa?EFN+xc$I;|EWe%Ng9ObAfUikBNiay*S`wuvK@ zw&>~wO|^cHI5WS|XjqJdby9A4a2BM`k@pWL@|Z3geP4tfbJorN{T$@WoMgL|ea^rhsSs^a+SK9mI4^;(zUSy1LCm3JP?IofL?@2cMS1k0+IAus zeX*&^6S+|Ua!}vGbibQ3anCfIB$i8&GNgKqg2mbbU=9{G!^H9sH|tV+#yJ$Pv!;Wk zIgx4IoigGB(>zq1h%*WB^ZRMw)n}`}$kHx1yXp&ZxB60)g}{kyX}r(k=2iZ{Kgag# zCWv{$C>{=r{{4>pU`BkN%g59^{^hfK$Vq-Wmo!P>sA+Q4xkN%$v_`u7NSA@{V{Zz@a9YjmdGL$;g7g5z*li?$w!pYmWAOPPxbLg&){)MD;J)1h;x#|`loDDcU6l`+^Bf`I3@4%Z zx$MaR6w~8R6lTU6naxcwY5uhaO5;VayMIE)LqTWu6Fe2n<*~o-w>SRzJOABp{cXSg z-kw4wy}b9=_xY~;2;Bw!P+)lx=_l1YS&zCAWq6)f(Nu-t_j5*LT?&F$pd{;@HhkFp z(bvm9GvFnu;w1b*wbjFO_uBtBSXo1Mj+gMr@o8E5GtkfiqQtWO5U4DPsLo59r-|SvS4477oM2uS6GFz zxqF5?z@xaAt0&O^T_?Uqaf1e8Gbz5OzROC&a(tZIt35OGh5*0ZK8Vm_V`|r5VxPlZ zEkalH-!|p%I#Rt4?>y$>69uoit5zKwtM_k`&cxW<7@oddm~~?uMxf+A5eFkI1^g|Z z$olg}N1~z3^Epb#u@kx#&zj$L&^sn#=GcSE$BZGaa`Q?d7QdZn7#GSsW|+X=vyb00 zy!<3Wi>(mINn1QfTL3~Uj|~$9KS!_{XiJ)sA>u6f2~8nTg~~R!NAl2NF>lYzv*LSP zL{wY&b=G=yjAtV(VLxyNxHhxIz`edI$>(^2MM+?ZIl5TQEyu3 z4-LGC)Bi>&Y+tJ@a3lv3mre{a%#ic#wn0A?ykUI@I`LY8H z7o>G!LVZV`vxe$eI4*fKw9A+O3gzfUJwK|)%@(_?So1(oreat5248zUl6wj?H(LbG}7J z$mP!Q`DML>rGhKdYmQJ-5TE}$IRvzNBaQ@CUDTrpHGkJ{`@jsX0U}P81Ht1#-`gEL zx(z`Qw&NTGo+~m)ATAmpw9zAdoJ?CK2FQ$EdiTn6LmpQ1-Li6%3a$CET^m1Tnt!7O zaS9D*EjDmEBdhYnrI>0tSN=Jp6CZ zz+@u)S;Rh8XGU))r&6xxpwr2AOw&6^e&jGCcgLRNlh0VdH=kYDyD*7@@V-6yX|d$8 zd4_BxZV0t7Uv1GF?fNZcAcJ+C*PMj@h3bs4ZO53XK7`WO{~6?h^plVoX+&4H#-bJP zJA<aehF=MXDSM z*XC}=i&o8hvwWADqTW6QJWSLu5Pk3)A9^~zJgrt^#d_NGlm-f6&=>Pk)z$BP=?-*UCjm)=?iA)DQ!5R3 zJ59RuttSWU<^CbS@P~at7vntg*ppDqP%90!hTa4lCjD(PAvPkX*`It(lc@9{;NFrH3uNCQ&16KE>y2jq09Qa=uQINYfiQ? zwH|4z-KZXvFb-6qp48b+cjCVjAJ_%}fS=W^EZamhWa)$V6q{&A?{wuYPr2UMroX@W z$E3gQI_b@aN%i{#C_lttrma?Pb&nuTFU3+_HZ>$%3zyvePg&yBc<00@}aj zY`b}TU6q4mej09j&Yp;jmg{q7-VRo?Z>7h^=jOZSw98wjVoR%r?A&{D0bbU)u)VpZ z4=~;`$Pk&}h-!iKZ*B_&5)%X?73~V3;FMI(H?JG0RSjU9a#;l%*xp_--zo^c`B<-L zd=0)o5gk0VK~8#h6V5TjCO|J2Qw753a4c?WHv!8~UdfIxPmCAm;-`io2|Yp&lUXDr z_iU*S&AwL?;*~-Y0_!o_z?=0})A}I&-g_3)b68g8NlonnDz9DHb!nWUD%s-F=`_`e-gb*^MC$Sx^o#Zp&NJLRA zvrc{fj?S$0XL18B%kPq=^OFMaY3T{E-XJ$dc@i#?FQgnT&V&*SWiYRUXRve+SDo~c z?z+IGQ*~S+W7sh=(k_E^B2KjSLY6Y>A-|^huZDJOGJ9J$|o$4kkHgz^nia;h9{@Q*0s;8i=A9if#GMSkpCez7c9R1Gr`T zIy5kQ^S(Cmv69@F5v0liQ^4Wr2{@0X=9fG>XOJ7HwsWXaIVLZfcS9OE%yx*#Ez=YfO6v%PSZi&Yj8IR)}#an66}E3CvQ$>`quLZ1s@6#%#gy z=XTw$e9la4qFJD&w&sjZE@AD8L{~k6Q9(XzEhGEpT&~zO4F}trt5CqGe+S>UqVDl}BNfip+`;;S%@CS-aWyUAOpa)> z&S&}bZ?aSW-9CVtZSmU5Qu`d=q(sh!hNg0!olW+z18r1#$j{BPbVL{rC6 zHF@FrD|{hr7<);heg1%d zA8o%XQB$=r88t|3s}mK@pC1qL()xTA8Od%#nX-w-&#)1&cAAyUbDqApc=pA1uiO~1 zjIVgi4L#M2moHvF{oCu}`O_EQ6<{KT0+sUQ1n(CR^V!I)>4 z%%BWqQXvxA#q==RMQY~w&jFkgfcI3x+@DJD2JF@*4I)WkPoHLa6^Gf+8hS^N{yqlZ|?5j3-?pDbBvYI@0mj@xdC!T=D1P5P~C z!sb`Lk3(0>ZH(cG2evO)7)%_kg{z}^gSK)h!q$oOCm<`?Q)FV(*i-SaMGZ`d_cT*n za`~8*Qi$VBiXZ>Se$)0tsm%9T+bb@9xN#cdo3UUW#Je~OQx-;@k*1Rvjc>IEBF$?f z2S1FS!wFDd3x6`>${g>WAvfid>{W9-s;AoBi1%6~^6@sLYB`>ZvX1i0_9BKEQ;y02 zpu!cCw5O6DAke%lfSWMTh_@x35JhE>Q9yfyr8o6cy6@*}AWBIOPE^c8K@~IF( zBWmS9H)l^&*J(h77_nkK$D>b7d$v2qV?8fcMS6P=?E>|gkC^H{F1k33|?Nv2Ja|quNrTXEa4h-ZrYK^>9rH9XRnJ)Y92BJVqM*S^N;g8^1nU&bN2-Q{o_ga z@#pYkzL5X^;qLK2&hOp1bF>%!Il+JL{VDwS&;K|-5fxMZdvfyUz3|WRTkQV%?Zn#M z4MOT$TfTex@obDi)pGlO3{Q0YV%)uu&JCuIVDJ6gX@xwwKSn^IU{cS3!G z$$Bpk5j0NKiC4Yf(}8>WY`f10k6`fMRL7jA-YP+_eYL$@^43A3t-vBh9U5n&N~B-& zf?p36$rfTm*hz%3K=`NF5-n)#P9fmO__7o_9!UX&A5A!OWU5)=kixBOL`Q}%pZ)Fm zQ#&?K*yS<=7+1Nz+s=m5>@#5YWmPU0a*AyMQCQ{(I+y&3Fd+$9e_^i%(vIEECG>jO z{(o`L7TDFDZ?;Q3&ymzM;W?@FeuJ@I>Q2QA;oXvnh!?UXnIN;D>!9%C)2LYmqXC9@ zrxIOk=b;Optm>=wP)4`+-Q@%ew?B1U{I>wX=t4;{Eh8kvU}EY6Vj@n^09Ej>=%m}Z zy*MdsG0+MK^v77om)U&V1)#+W008BX%@^}|K^5}`G)ji~?Bg(K9j~i=k5iy5=9Wn> znv!M~duNCTRdoI4ZI-S3?L(X-nAd=;ak?J3FH$QcSC1xVkt=8ou&}37}uBZYDC3k9^o_duIHkziyjm z^!fZU#M{#mI8+%GV;6SO@F(GtcC}`J#8G07S>Y*bWP*N^?6 zw1Z9V8{G}+jujR^MV2dM#Lo$nRh3TZy z=bzo_twV|NTtcx`;E4W8y!5bZF3-jcjPlsD6~+St>M(bLf-3?z42~FU(0>f6b$Y*^ zEV0yAug>PHI`)}bHhQ~cxULdWyj2eF*6@rj`Q=7(jwH1UW3N+x`XN&h;Wzex@Zc?UX*vlv$+ zEL~(E&fl-KEWc^oUflBZma<@<$=j(ciF}9e%6L){aO!O$O`*q*)G*(3K!We%z{-ve zFQX~_U9Q1NGW;jn{7Pf!+564BHuA;YvUDVsc79&k;|I+TBnyZ=>N+Gnc5y@nAuY*6XHXdtoPyisg+oP8fq>)1ACqE0nyHlONfEk zIQ-hZ@%ksz7C&}wDj&tb9@~aryEa~*#di2HbQjn?|EQesF}3XRiB*z}4F0MuO_hMc zQLnZu$NWum1Uap66AN(|*OITRHNeCDPgPGp1tmOcdp`e&EzKp1DriH-hyB}@12gOL(aV&7Qthey_7BC2p7^3FSSB=eTR=kGycvXihnf1|+A}@Xu zQ#-*0i`iXJgN1k62pF4r75?gc1%*GXOcRIQ5-fCq7rp`J=vOK>o*FsEqe=&!DM@XD)ys4NfG{1RsnI?ZOS%2 z3|5OzWLjt9BO>iY zv62_sz-MueMG2axSMsX*wi1ZG{oTgkph z2)Ctrz@bJ*)Jbtr(ZSgF9qC{gT&Vw3r1XB8-_)~FtQow$%8kC6Y$`GbAyaUf#@~ep zPqjRTL=9xyJTF(rN*a4P#->~ZJqs;r(jfo`FNETP%SONg8er57Jkd_)@2cb04XwFO z5?Y5*a#wuzlvx;Le04~_rcMv*6<*5$1 zmH9|>$4Qmr6nhXav@bc4!!c{ut0rD;z|Y5IXS-;TLM^S(@m&>^u&z>1qV!Cfegl3l zFIL}#XGz;je4S)`lH@11GrYOxHx^ELiQDTabUMF0YRDU{rPP84HzY2%^j_G1%TU64 z@nReLN;1q2IPS*JZz>&I3iAhK_fL6NOeH!F z8k!$~)z;GXJnD3T6v0T4B)g%XmMWPsZt~o?)^TWkj&lN0{|vN_r|OUi_M8ve6$-q- z^v-+M0qDH{k^%yM6xKQOZkNY0qj*HZ*AVI67@fpq%*H*;o-PI?R+=er;e6@&5YZfg z`RWi^f=1KyVWiE0Ga)CwgjWNDSYF`e|7y)31a0Pz2raCTd6HsiM|tm2TpTR}0AiSb zRJv2{P`hh*PoI1a79Tek6-5m9IhUh6<2t=FLYddY#1?7>XS**#WIlv1nravl{)n%5 zXr=SJM1Ge1yx8$&G78+wysvlWCPEZ zoAA!Bn{2Vw7E!oQMah{JkFD>1rRq&gr&=Y+qV$PU-6BZY+{W5a-`ux zR7dABw4w!cV5E>DJWWcy1X0IvgGt-=RGG;rJGt<(!49fAFu~W=2ZAJXo5{2<%Tz_+ zW7zBDBjN0&PtDSdaI7N1bQaZl{kP&iGcF~ie-EVxJ>x*vn@1O77zp*JMTjet4k8pa zZV;q-F7>}lsDg_C17eSu;YSihY;mde_@au{@OL^~0Q?>Pa|=y=hyOf4WRBm-f6NH| z`U~)A?#_fKxX~}Ipn(s}I6r36esOr2EN#&=s>>i*A*ND)%0~U{mWN$IVc`2{ZHbOM zD0}d?t0Gh`_R+FOIQ{BHRx zE=4|6xR3b8ZtZ%Q4N~0upTIey20&I0i zHnE1Lyi#jBv-$+T=GO}&`i!QwVRMYWTpbsz9?rex_M$AY-+d_CgrK~zkOTCxDT6UH z#)6RYsm5eeKLXkKc^Rd4+t|gdf8XJsS%IRpo2TErO0#Q>9a?ueu^RP+cQVB8xXAei z{Gu1){-Lf#-KWkYjlaf`6dDLfQ7$zvb+uyX1bo2LchHza5M9}ja=i+6Qb#y*QVnpg z)R#HZ?@_m_FZY6$?LF+}Z1)Sm^D!E^nl_e_aUej7P0Jf*gshe04BNTZw=uj9T`6V~ zhN*Pai_~$zYV^3O-;e$Bw;g&;8M3vosB77MrESk%J2f{GrZ@cjw9eKcwFd0fb{=-e zMAaZgg}?hwt?Y^!D{NmD7#s-poe?FZ?$9d1H=*s1zdvd0)DVFaeTAgXaA3CNY7zY6 z+;rl)kPp)W&i3bLSFQuO8~g5TCa)pgGH}rPEKGzz`;u=FPO`p9Oe*i%sOwN3XIja# z=)&1D4@XVp9!z}3tma<6x`R&RU$Q=H>Lf|!PtuSC3P>NTov@oAX!za{GL)C@d|?;N zq2iKT;41qRH};wUoUbHDO?Gd%{Ecq&4t!LfOH6?|9>gHH-Uu7>sL4+z*I}SH?)s~m zX9EJj1$>3szr^lB;eK8Q6G*t~STy;@_kvQvXPmfq2yx>H0$*rXg)Na)$_1mq;A)zY zWB5omToX1_sl$t3!a(bwzRs8HRoQXEAV}N?@GZs^l$n|_S$nC?^^v6N*d~#j);&oQ zLm^3OPo1WLQon5jd$UkaJSPyKVck%jT7-@lS89mQ$~VMw9Z*;hEf{1$UoU3%+^Sv( zGd5ta7FYJ>10>l|)2qF)KJh6K$vEMy`e4kYe6;s8zKD$}4$vlj;kh{13lnsrw#Rp* z^x$y8#4&!a7a z_CH?T=Ig}>(};EhgFARKXR=C0)*74TuM|{=A;y6QQ!_5cT}}tC4@phE^et4<2lLb7 zbYzPkAV6!x$`fS=BY1{y2NoM^rHVCBiO-z*$q_1-AYg@uypw*;^UEkZoj>=^AqB|b z4C>URVK>^h^n;9{!u@KEdP|?h!hf-8O9=pTi~){~VGNqgz3>`iT z?j}SMTZO7i#nonqqfvSOhgXJ1t@qYgV*lwdK4p`@> zjg-%4u)(;dsnJXd2%oyR576MxBKFe0YOaxwO4T3d#eeIwF3Cc_UPHnLH>@{w?tJ?* z-E!gXux?#*r_`C?`2}vpjot?st1mE>A1cmk`@D+`v_7lKMH^@A4-977 zDW715XmusYG>W{jc{6oVM* zA#wDRjhT>JD3}v$y^!gGf5jh<#QS5c^e~#@shAI|Z`d*CC?uOTTv5E>VFT|Q*Ycxf z2NF1#pC}y)7;WNrBcuTzOVKTQ=s2maVWwOfw7;lo{U{gD61!qGLX6@#zs`rjb@Q(d z5j3?$SJ@1)j2a#Lo^9Lkgm? zT@#6zkt;n$G@mDSouQP`dzSUK<<5z2(EZpOku)f8bU(eG7;@y@u04(WGeH>kp|2cF zn2hLWVeW_jPK_7HeqnS*+wB+I1n zA%zU@op=N`@q!ZFA%(;{EEfao2esYfVD67sO84T!AlpMIkTV)PvjuIH?7b8Ti9CM0an~gJ9aa8;cJf zh1F`n?+T_r4*4BlqCeWE$k>=j(Gnkz3w8_ul}<%(M8F@ZT>dCx!?jS7%I8$SOr=~5 z6xag*TqR@pae{0IE=r&sLFW#@6LA`Crw2aL;LfURf}>m2{WWL@P7|DX45P9Tb1!z; zXhO~E7mwZz&)a%a1;OoR$?&+N`97}>)s07@A{}Xw>iV^V7HKd`n|C%JXx$ra+%d=8 zO}G|V(Csh|(gwsfQFZ7Pvv0D3-ZAF5jd}Y1FEvGHf zJcvI0H1Q@(YEsh#hyCVXHualuv!#7O*XQSWJ~lqV1@p9M1N2P`6E+V&Y$Q9KgwP6J zMvu0_O_C0(?8fagzhVGLiF80N&H%6x_|k$M!K6V8Z`^2qPCP~U{Oxt~`fZ$YF%%L} z8%#__?%BF?YoeO{LTuLSrF4E!Fns}@K$fQmvfD2fco7K(zra%`$*6Mn@jw`h&lFJ! z1}#iJ95`3yD0w0LlcFGhB5vEZd>ebmiARj#7yHd1q&LMUrqqeOer9{UBR`}ceVU`g z!}kB7JljS%BA-^}d}9r|+qI_XuvvIcM17!Pw%XooEQa*nS@4()7ouX_y!7OmCHmSZ z5WGf&x0iNBJ6~uzD-#pQl7<_jQg%28q$~gY>K)zf{qgN)xKL!Y5l;O=j1Vr~W z)x<2X=5^DBMsW}wK!}!J?b+H1{{gqrG_on1Fh$-`@UsFtAdhGD@|BFZTGkAVU9Rw~ zG-$da%i^~Ly+8eNVxMBJ>mED_7KjRW6~c;@JZfIbwRLjY-MjqdfMT=IfaebE zyREbHBiYoJmoataqi>$g#7eR)IpMt87IpY!5)zm;m;N_FgyJNG9$mFQB2(DzMDm|9 z6an7<{s&&t{YUEzadSop8tY-Trriah{9q|4>JogRA-UOqJu9BCYm~?I3i^e?;n|;j zL#%<2(jxdJi0%aA4oub!tFoV7%<(tTd^&eHCRT&&ZMe(n0$B~MbPDf`6!Cj4r{AUQORJ1HxV*qBBWk!ZF9KXdQ= z%(2YO+`y~wnVS#~Th^@s%!2U%Jm`cDMhq5Vz{Ik#Se-=!o;Lfpfop?Z&(TX z2o$@Zlbo-@{mtktP74Xli6_-2WT14|usCVl<#8zmgL|C7NSW&cwDa$tlfw@NRt0Wn z*EsYxg)=0fh+n#AIRdZG!r`Zy#*}H9CrAFUX6a+1aqOE7CfZsMX~9M7=^Ug{N9^4n zWK(?@eiT-u=^=ZZNQzKTkoSi|=0FF%ld=17+zr|_Ub|!K3aSv=ot!Ucqy9C=)AXw~ zPSj&FvoTUh(k1ZO5C5HZN)hOEzX-%hR^R!#roCBhi18wjc&JA?PU1a;}hX@S|#rMK54H{a^Kvu$VQ z6XZA@dPl5jqU}7RGy=7L2Q1?RH*-TXzV*MzxKc&r;8A7$sQ_!5g2$vzg0s&Li}k8` zzvXDrdok=yuEhgTo=9d%?wf`=h%duD%lH;O)RqP1rbf2v(-0ii(XRK3lC3=f^1|PE z+m~C$Ux76M(HyD2F;od(P{g~cnM759QWd_wmqU3S;m|N~F<))zx`FL)+j{KNbADVS z#0MJFunSa_IPc})i}L- zpK7$8#74>>zJHDjLA%|6^#cdp^{YLM4^_<$gnFsO4@N4ftwUmrL?WtXDFBMU4jATR zgWON0?YwbY9kU;E8z>GU#l5sLg%IOH;>ms~N-txo+%Pn`2adsD0vxgii?fk0GZuZamG~c1IX#pjbLV)PZ>mFz@$5 zBdP?4dc7do$WhDnLc00Oyq!cxGH=IlYhXVQ!$0v-a-`82N0X3t-6g4&rbt5Gv@7-r z>kuV;XunT@daZ}=pt@f}JWjgh!!oWMe@e9~kozmggt8xQ4y=N*mbCl8V_QV?j zjnQbzu2Y%Tyc(Jio1QU#6)cMB7+FS<2x<+PWMb9Y)HTsjd_So$^sRT)IcDB1wV&u$5Rs$|cH`xx=;IKt#SGULkHaBu8Wy0B_>!Kj z?SYsSFe<;qJsfwW5n=b5MgY5e$mm@IKTx6(RN#{lUyE32meVZR(82a?iR{DfA-&jl z2l7F#`@vGy>hYki*xocij-ROab2m+<5R%?ck#@>@rpp2SdIvOOWFL!0EFAMshY72I zh9Fr$<<(`qEl(SK_}O>wMq;|MEg45le@OfXk2#jaqb8_|!QB>*>B-=+XZaxZi5`z& z5Dgqt4E*-3dE1Q@So`rN=*7uWgl?r*pzvvUd2&*hTR(iZctkU39DY*Vh&4*&YIVFk zUz7|R<@8J%09?Q@Qdy$>_v;)Kc0+bjeRQRw!^%Py7=h?ElmPpFr)Am!v2)-DeC%mF z0Y*b$@Tt!(;%}sW;|L_x{0SA`vU13@#$P!>1E&MWsoK7WW$#>zTf6)rUoiN<#K_bO zLOg8gOfHjo`yu5wVgmts$8oGi=!FxNTea?6@0D%))h?64oK`XS44Pn-gj9ie=ndRzWJzyJ`w=s4dKc zo9e$5=Y0N&183kd`(S=k>X>W5VKlYyy4;SOoZEcHpRp1@a3s&q%P!OD|%}-8n zwiJ=SocJ)UFD#gvOyT3#l z-V9yb6dD>PEN+o))?xQ0O=R;R5pk^1>5)QL(GcIyXR+rS4D48WbP%(X_zd^Q)(LpG z&tidD@SGGG*ZT@

    6@mP8syAeZMT8X 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 literal 0 HcmV?d00001 diff --git a/supervisor/api/panel/chunk.212065a6c485fbc07bb8.js b/supervisor/api/panel/chunk.212065a6c485fbc07bb8.js new file mode 100644 index 000000000..fba467133 --- /dev/null +++ b/supervisor/api/panel/chunk.212065a6c485fbc07bb8.js @@ -0,0 +1,52699 @@ +(self["webpackJsonp"] = self["webpackJsonp"] || []).push([[12],[ +/* 0 */, +/* 1 */, +/* 2 */, +/* 3 */, +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/legacy/legacy-element-mixin.js + 9 modules +var legacy_element_mixin = __webpack_require__(133); + +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/legacy/polymer-fn.js +var polymer_fn = __webpack_require__(8); + +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/utils/boot.js +var boot = __webpack_require__(10); + +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/mixins/property-effects.js + 1 modules +var property_effects = __webpack_require__(103); + +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/utils/mixin.js +var mixin = __webpack_require__(19); + +// CONCATENATED MODULE: ./node_modules/@polymer/polymer/lib/mixins/mutable-data.js +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +/** +@license +Copyright (c) 2017 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + // Common implementation for mixin & behavior + +function mutablePropertyChange(inst, property, value, old, mutableData) { + var isObject; + + if (mutableData) { + isObject = _typeof(value) === 'object' && value !== null; // Pull `old` for Objects from temp cache, but treat `null` as a primitive + + if (isObject) { + old = inst.__dataTemp[property]; + } + } // Strict equality check, but return false for NaN===NaN + + + var shouldChange = old !== value && (old === old || value === value); // Objects are stored in temporary cache (cleared at end of + // turn), which is used for dirty-checking + + if (isObject && shouldChange) { + inst.__dataTemp[property] = value; + } + + return shouldChange; +} +/** + * Element class mixin to skip strict dirty-checking for objects and arrays + * (always consider them to be "dirty"), for use on elements utilizing + * `PropertyEffects` + * + * By default, `PropertyEffects` performs strict dirty checking on + * objects, which means that any deep modifications to an object or array will + * not be propagated unless "immutable" data patterns are used (i.e. all object + * references from the root to the mutation were changed). + * + * Polymer also provides a proprietary data mutation and path notification API + * (e.g. `notifyPath`, `set`, and array mutation API's) that allow efficient + * mutation and notification of deep changes in an object graph to all elements + * bound to the same object graph. + * + * In cases where neither immutable patterns nor the data mutation API can be + * used, applying this mixin will cause Polymer to skip dirty checking for + * objects and arrays (always consider them to be "dirty"). This allows a + * user to make a deep modification to a bound object graph, and then either + * simply re-set the object (e.g. `this.items = this.items`) or call `notifyPath` + * (e.g. `this.notifyPath('items')`) to update the tree. Note that all + * elements that wish to be updated based on deep mutations must apply this + * mixin or otherwise skip strict dirty checking for objects/arrays. + * Specifically, any elements in the binding tree between the source of a + * mutation and the consumption of it must apply this mixin or enable the + * `OptionalMutableData` mixin. + * + * In order to make the dirty check strategy configurable, see + * `OptionalMutableData`. + * + * Note, the performance characteristics of propagating large object graphs + * will be worse as opposed to using strict dirty checking with immutable + * patterns or Polymer's path notification API. + * + * @mixinFunction + * @polymer + * @summary Element class mixin to skip strict dirty-checking for objects + * and arrays + */ + + +var MutableData = Object(mixin["a" /* dedupingMixin */])(function (superClass) { + /** + * @polymer + * @mixinClass + * @implements {Polymer_MutableData} + */ + var MutableData = /*#__PURE__*/function (_superClass) { + _inherits(MutableData, _superClass); + + var _super = _createSuper(MutableData); + + function MutableData() { + _classCallCheck(this, MutableData); + + return _super.apply(this, arguments); + } + + _createClass(MutableData, [{ + key: "_shouldPropertyChange", + + /** + * Overrides `PropertyEffects` to provide option for skipping + * strict equality checking for Objects and Arrays. + * + * This method pulls the value to dirty check against from the `__dataTemp` + * cache (rather than the normal `__data` cache) for Objects. Since the temp + * cache is cleared at the end of a turn, this implementation allows + * side-effects of deep object changes to be processed by re-setting the + * same object (using the temp cache as an in-turn backstop to prevent + * cycles due to 2-way notification). + * + * @param {string} property Property name + * @param {*} value New property value + * @param {*} old Previous property value + * @return {boolean} Whether the property should be considered a change + * @protected + */ + value: function _shouldPropertyChange(property, value, old) { + return mutablePropertyChange(this, property, value, old, true); + } + }]); + + return MutableData; + }(superClass); + + return MutableData; +}); +/** + * Element class mixin to add the optional ability to skip strict + * dirty-checking for objects and arrays (always consider them to be + * "dirty") by setting a `mutable-data` attribute on an element instance. + * + * By default, `PropertyEffects` performs strict dirty checking on + * objects, which means that any deep modifications to an object or array will + * not be propagated unless "immutable" data patterns are used (i.e. all object + * references from the root to the mutation were changed). + * + * Polymer also provides a proprietary data mutation and path notification API + * (e.g. `notifyPath`, `set`, and array mutation API's) that allow efficient + * mutation and notification of deep changes in an object graph to all elements + * bound to the same object graph. + * + * In cases where neither immutable patterns nor the data mutation API can be + * used, applying this mixin will allow Polymer to skip dirty checking for + * objects and arrays (always consider them to be "dirty"). This allows a + * user to make a deep modification to a bound object graph, and then either + * simply re-set the object (e.g. `this.items = this.items`) or call `notifyPath` + * (e.g. `this.notifyPath('items')`) to update the tree. Note that all + * elements that wish to be updated based on deep mutations must apply this + * mixin or otherwise skip strict dirty checking for objects/arrays. + * Specifically, any elements in the binding tree between the source of a + * mutation and the consumption of it must enable this mixin or apply the + * `MutableData` mixin. + * + * While this mixin adds the ability to forgo Object/Array dirty checking, + * the `mutableData` flag defaults to false and must be set on the instance. + * + * Note, the performance characteristics of propagating large object graphs + * will be worse by relying on `mutableData: true` as opposed to using + * strict dirty checking with immutable patterns or Polymer's path notification + * API. + * + * @mixinFunction + * @polymer + * @summary Element class mixin to optionally skip strict dirty-checking + * for objects and arrays + */ + +var OptionalMutableData = Object(mixin["a" /* dedupingMixin */])(function (superClass) { + /** + * @mixinClass + * @polymer + * @implements {Polymer_OptionalMutableData} + */ + var OptionalMutableData = /*#__PURE__*/function (_superClass2) { + _inherits(OptionalMutableData, _superClass2); + + var _super2 = _createSuper(OptionalMutableData); + + function OptionalMutableData() { + _classCallCheck(this, OptionalMutableData); + + return _super2.apply(this, arguments); + } + + _createClass(OptionalMutableData, [{ + key: "_shouldPropertyChange", + + /** + * Overrides `PropertyEffects` to provide option for skipping + * strict equality checking for Objects and Arrays. + * + * When `this.mutableData` is true on this instance, this method + * pulls the value to dirty check against from the `__dataTemp` cache + * (rather than the normal `__data` cache) for Objects. Since the temp + * cache is cleared at the end of a turn, this implementation allows + * side-effects of deep object changes to be processed by re-setting the + * same object (using the temp cache as an in-turn backstop to prevent + * cycles due to 2-way notification). + * + * @param {string} property Property name + * @param {*} value New property value + * @param {*} old Previous property value + * @return {boolean} Whether the property should be considered a change + * @protected + */ + value: function _shouldPropertyChange(property, value, old) { + return mutablePropertyChange(this, property, value, old, this.mutableData); + } + }], [{ + key: "properties", + get: function get() { + return { + /** + * Instance-level flag for configuring the dirty-checking strategy + * for this element. When true, Objects and Arrays will skip dirty + * checking, otherwise strict equality checking will be used. + */ + mutableData: Boolean + }; + } + }]); + + return OptionalMutableData; + }(superClass); + + return OptionalMutableData; +}); // Export for use by legacy behavior + +MutableData._mutablePropertyChange = mutablePropertyChange; +// EXTERNAL MODULE: ./node_modules/@polymer/polymer/lib/utils/settings.js +var settings = __webpack_require__(25); + +// CONCATENATED MODULE: ./node_modules/@polymer/polymer/lib/utils/templatize.js +function templatize_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { templatize_typeof = function _typeof(obj) { return typeof obj; }; } else { templatize_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return templatize_typeof(obj); } + +function templatize_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function templatize_createClass(Constructor, protoProps, staticProps) { if (protoProps) templatize_defineProperties(Constructor.prototype, protoProps); if (staticProps) templatize_defineProperties(Constructor, staticProps); return Constructor; } + +function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } + +function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = templatize_getPrototypeOf(object); if (object === null) break; } return object; } + +function templatize_inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) templatize_setPrototypeOf(subClass, superClass); } + +function templatize_setPrototypeOf(o, p) { templatize_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return templatize_setPrototypeOf(o, p); } + +function templatize_createSuper(Derived) { return function () { var Super = templatize_getPrototypeOf(Derived), result; if (templatize_isNativeReflectConstruct()) { var NewTarget = templatize_getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return templatize_possibleConstructorReturn(this, result); }; } + +function templatize_possibleConstructorReturn(self, call) { if (call && (templatize_typeof(call) === "object" || typeof call === "function")) { return call; } return templatize_assertThisInitialized(self); } + +function templatize_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function templatize_isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } + +function templatize_getPrototypeOf(o) { templatize_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return templatize_getPrototypeOf(o); } + +function templatize_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** +@license +Copyright (c) 2017 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +/** + * Module for preparing and stamping instances of templates that utilize + * Polymer's data-binding and declarative event listener features. + * + * Example: + * + * // Get a template from somewhere, e.g. light DOM + * let template = this.querySelector('template'); + * // Prepare the template + * let TemplateClass = Templatize.templatize(template); + * // Instance the template with an initial data model + * let instance = new TemplateClass({myProp: 'initial'}); + * // Insert the instance's DOM somewhere, e.g. element's shadow DOM + * this.shadowRoot.appendChild(instance.root); + * // Changing a property on the instance will propagate to bindings + * // in the template + * instance.myProp = 'new value'; + * + * The `options` dictionary passed to `templatize` allows for customizing + * features of the generated template class, including how outer-scope host + * properties should be forwarded into template instances, how any instance + * properties added into the template's scope should be notified out to + * the host, and whether the instance should be decorated as a "parent model" + * of any event handlers. + * + * // Customize property forwarding and event model decoration + * let TemplateClass = Templatize.templatize(template, this, { + * parentModel: true, + * forwardHostProp(property, value) {...}, + * instanceProps: {...}, + * notifyInstanceProp(instance, property, value) {...}, + * }); + * + * @summary Module for preparing and stamping instances of templates + * utilizing Polymer templating features. + */ + + + + // Base class for HTMLTemplateElement extension that has property effects +// machinery for propagating host properties to children. This is an ES5 +// class only because Babel (incorrectly) requires super() in the class +// constructor even though no `this` is used and it returns an instance. + +var newInstance = null; +/** + * @constructor + * @extends {HTMLTemplateElement} + * @private + */ + +function HTMLTemplateElementExtension() { + return newInstance; +} + +HTMLTemplateElementExtension.prototype = Object.create(HTMLTemplateElement.prototype, { + constructor: { + value: HTMLTemplateElementExtension, + writable: true + } +}); +/** + * @constructor + * @implements {Polymer_PropertyEffects} + * @extends {HTMLTemplateElementExtension} + * @private + */ + +var DataTemplate = Object(property_effects["a" /* PropertyEffects */])(HTMLTemplateElementExtension); +/** + * @constructor + * @implements {Polymer_MutableData} + * @extends {DataTemplate} + * @private + */ + +var MutableDataTemplate = MutableData(DataTemplate); // Applies a DataTemplate subclass to a