From 0225bdb772d1334cc1aa7ab0fc3678df0864df6b Mon Sep 17 00:00:00 2001 From: AlisaLinUwU Date: Sun, 26 Jan 2025 10:42:28 +0500 Subject: Initialize --- .../static/plugins/summernote/summernote-lite.js | 10783 +++++++++++++++++++ 1 file changed, 10783 insertions(+) create mode 100644 src/main/resources/static/plugins/summernote/summernote-lite.js (limited to 'src/main/resources/static/plugins/summernote/summernote-lite.js') diff --git a/src/main/resources/static/plugins/summernote/summernote-lite.js b/src/main/resources/static/plugins/summernote/summernote-lite.js new file mode 100644 index 0000000..022e7b7 --- /dev/null +++ b/src/main/resources/static/plugins/summernote/summernote-lite.js @@ -0,0 +1,10783 @@ +/*! + * + * Super simple WYSIWYG editor v0.8.20 + * https://summernote.org + * + * + * Copyright 2013- Alan Hong and contributors + * Summernote may be freely distributed under the MIT license. + * + * Date: 2021-10-14T21:15Z + * + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("jQuery")); + else if(typeof define === 'function' && define.amd) + define(["jQuery"], factory); + else { + var a = typeof exports === 'object' ? factory(require("jQuery")) : factory(root["jQuery"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(self, function(__WEBPACK_EXTERNAL_MODULE__1145__) { +return /******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ 9770: +/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => { + +/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1145); +/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__); + +(jquery__WEBPACK_IMPORTED_MODULE_0___default().summernote) = (jquery__WEBPACK_IMPORTED_MODULE_0___default().summernote) || { + lang: {} +}; +jquery__WEBPACK_IMPORTED_MODULE_0___default().extend((jquery__WEBPACK_IMPORTED_MODULE_0___default().summernote.lang), { + 'en-US': { + font: { + bold: 'Bold', + italic: 'Italic', + underline: 'Underline', + clear: 'Remove Font Style', + height: 'Line Height', + name: 'Font Family', + strikethrough: 'Strikethrough', + subscript: 'Subscript', + superscript: 'Superscript', + size: 'Font Size', + sizeunit: 'Font Size Unit' + }, + image: { + image: 'Picture', + insert: 'Insert Image', + resizeFull: 'Resize full', + resizeHalf: 'Resize half', + resizeQuarter: 'Resize quarter', + resizeNone: 'Original size', + floatLeft: 'Float Left', + floatRight: 'Float Right', + floatNone: 'Remove float', + shapeRounded: 'Shape: Rounded', + shapeCircle: 'Shape: Circle', + shapeThumbnail: 'Shape: Thumbnail', + shapeNone: 'Shape: None', + dragImageHere: 'Drag image or text here', + dropImage: 'Drop image or Text', + selectFromFiles: 'Select from files', + maximumFileSize: 'Maximum file size', + maximumFileSizeError: 'Maximum file size exceeded.', + url: 'Image URL', + remove: 'Remove Image', + original: 'Original' + }, + video: { + video: 'Video', + videoLink: 'Video Link', + insert: 'Insert Video', + url: 'Video URL', + providers: '(YouTube, Google Drive, Vimeo, Vine, Instagram, DailyMotion, Youku, Peertube)' + }, + link: { + link: 'Link', + insert: 'Insert Link', + unlink: 'Unlink', + edit: 'Edit', + textToDisplay: 'Text to display', + url: 'To what URL should this link go?', + openInNewWindow: 'Open in new window', + useProtocol: 'Use default protocol' + }, + table: { + table: 'Table', + addRowAbove: 'Add row above', + addRowBelow: 'Add row below', + addColLeft: 'Add column left', + addColRight: 'Add column right', + delRow: 'Delete row', + delCol: 'Delete column', + delTable: 'Delete table' + }, + hr: { + insert: 'Insert Horizontal Rule' + }, + style: { + style: 'Style', + p: 'Normal', + blockquote: 'Quote', + pre: 'Code', + h1: 'Header 1', + h2: 'Header 2', + h3: 'Header 3', + h4: 'Header 4', + h5: 'Header 5', + h6: 'Header 6' + }, + lists: { + unordered: 'Unordered list', + ordered: 'Ordered list' + }, + options: { + help: 'Help', + fullscreen: 'Full Screen', + codeview: 'Code View' + }, + paragraph: { + paragraph: 'Paragraph', + outdent: 'Outdent', + indent: 'Indent', + left: 'Align left', + center: 'Align center', + right: 'Align right', + justify: 'Justify full' + }, + color: { + recent: 'Recent Color', + more: 'More Color', + background: 'Background Color', + foreground: 'Text Color', + transparent: 'Transparent', + setTransparent: 'Set transparent', + reset: 'Reset', + resetToDefault: 'Reset to default', + cpSelect: 'Select' + }, + shortcut: { + shortcuts: 'Keyboard shortcuts', + close: 'Close', + textFormatting: 'Text formatting', + action: 'Action', + paragraphFormatting: 'Paragraph formatting', + documentStyle: 'Document Style', + extraKeys: 'Extra keys' + }, + help: { + 'escape': 'Escape', + 'insertParagraph': 'Insert Paragraph', + 'undo': 'Undo the last command', + 'redo': 'Redo the last command', + 'tab': 'Tab', + 'untab': 'Untab', + 'bold': 'Set a bold style', + 'italic': 'Set a italic style', + 'underline': 'Set a underline style', + 'strikethrough': 'Set a strikethrough style', + 'removeFormat': 'Clean a style', + 'justifyLeft': 'Set left align', + 'justifyCenter': 'Set center align', + 'justifyRight': 'Set right align', + 'justifyFull': 'Set full align', + 'insertUnorderedList': 'Toggle unordered list', + 'insertOrderedList': 'Toggle ordered list', + 'outdent': 'Outdent on current paragraph', + 'indent': 'Indent on current paragraph', + 'formatPara': 'Change current block\'s format as a paragraph(P tag)', + 'formatH1': 'Change current block\'s format as H1', + 'formatH2': 'Change current block\'s format as H2', + 'formatH3': 'Change current block\'s format as H3', + 'formatH4': 'Change current block\'s format as H4', + 'formatH5': 'Change current block\'s format as H5', + 'formatH6': 'Change current block\'s format as H6', + 'insertHorizontalRule': 'Insert horizontal rule', + 'linkDialog.show': 'Show Link Dialog' + }, + history: { + undo: 'Undo', + redo: 'Redo' + }, + specialChar: { + specialChar: 'SPECIAL CHARACTERS', + select: 'Select Special characters' + }, + output: { + noSelection: 'No Selection Made!' + } + } +}); + +/***/ }), + +/***/ 1145: +/***/ ((module) => { + +module.exports = __WEBPACK_EXTERNAL_MODULE__1145__; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXTERNAL MODULE: external "jQuery" +var external_jQuery_ = __webpack_require__(1145); +var external_jQuery_default = /*#__PURE__*/__webpack_require__.n(external_jQuery_); +// EXTERNAL MODULE: ./src/lang/summernote-en-US.js +var summernote_en_US = __webpack_require__(9770); +;// CONCATENATED MODULE: ./src/js/core/env.js + +/** + * returns whether font is installed or not. + * + * @param {String} fontName + * @return {Boolean} + */ + +var genericFontFamilies = ['sans-serif', 'serif', 'monospace', 'cursive', 'fantasy']; + +function validFontName(fontName) { + return external_jQuery_default().inArray(fontName.toLowerCase(), genericFontFamilies) === -1 ? "'".concat(fontName, "'") : fontName; +} + +function isFontInstalled(fontName) { + var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS'; + var testText = 'mmmmmmmmmmwwwww'; + var testSize = '200px'; + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + context.font = testSize + " '" + testFontName + "'"; + var originalWidth = context.measureText(testText).width; + context.font = testSize + ' ' + validFontName(fontName) + ', "' + testFontName + '"'; + var width = context.measureText(testText).width; + return originalWidth !== width; +} + +var userAgent = navigator.userAgent; +var isMSIE = /MSIE|Trident/i.test(userAgent); +var browserVersion; + +if (isMSIE) { + var matches = /MSIE (\d+[.]\d+)/.exec(userAgent); + + if (matches) { + browserVersion = parseFloat(matches[1]); + } + + matches = /Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(userAgent); + + if (matches) { + browserVersion = parseFloat(matches[1]); + } +} + +var isEdge = /Edge\/\d+/.test(userAgent); +var isSupportTouch = 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; // [workaround] IE doesn't have input events for contentEditable +// - see: https://goo.gl/4bfIvA + +var inputEventName = isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input'; +/** + * @class core.env + * + * Object which check platform and agent + * + * @singleton + * @alternateClassName env + */ + +/* harmony default export */ const env = ({ + isMac: navigator.appVersion.indexOf('Mac') > -1, + isMSIE: isMSIE, + isEdge: isEdge, + isFF: !isEdge && /firefox/i.test(userAgent), + isPhantom: /PhantomJS/i.test(userAgent), + isWebkit: !isEdge && /webkit/i.test(userAgent), + isChrome: !isEdge && /chrome/i.test(userAgent), + isSafari: !isEdge && /safari/i.test(userAgent) && !/chrome/i.test(userAgent), + browserVersion: browserVersion, + isSupportTouch: isSupportTouch, + isFontInstalled: isFontInstalled, + isW3CRangeSupport: !!document.createRange, + inputEventName: inputEventName, + genericFontFamilies: genericFontFamilies, + validFontName: validFontName +}); +;// CONCATENATED MODULE: ./src/js/core/func.js + +/** + * @class core.func + * + * func utils (for high-order func's arg) + * + * @singleton + * @alternateClassName func + */ + +function eq(itemA) { + return function (itemB) { + return itemA === itemB; + }; +} + +function eq2(itemA, itemB) { + return itemA === itemB; +} + +function peq2(propName) { + return function (itemA, itemB) { + return itemA[propName] === itemB[propName]; + }; +} + +function ok() { + return true; +} + +function fail() { + return false; +} + +function not(f) { + return function () { + return !f.apply(f, arguments); + }; +} + +function and(fA, fB) { + return function (item) { + return fA(item) && fB(item); + }; +} + +function func_self(a) { + return a; +} + +function invoke(obj, method) { + return function () { + return obj[method].apply(obj, arguments); + }; +} + +var idCounter = 0; +/** + * reset globally-unique id + * + */ + +function resetUniqueId() { + idCounter = 0; +} +/** + * generate a globally-unique id + * + * @param {String} [prefix] + */ + + +function uniqueId(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; +} +/** + * returns bnd (bounds) from rect + * + * - IE Compatibility Issue: http://goo.gl/sRLOAo + * - Scroll Issue: http://goo.gl/sNjUc + * + * @param {Rect} rect + * @return {Object} bounds + * @return {Number} bounds.top + * @return {Number} bounds.left + * @return {Number} bounds.width + * @return {Number} bounds.height + */ + + +function rect2bnd(rect) { + var $document = external_jQuery_default()(document); + return { + top: rect.top + $document.scrollTop(), + left: rect.left + $document.scrollLeft(), + width: rect.right - rect.left, + height: rect.bottom - rect.top + }; +} +/** + * returns a copy of the object where the keys have become the values and the values the keys. + * @param {Object} obj + * @return {Object} + */ + + +function invertObject(obj) { + var inverted = {}; + + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + inverted[obj[key]] = key; + } + } + + return inverted; +} +/** + * @param {String} namespace + * @param {String} [prefix] + * @return {String} + */ + + +function namespaceToCamel(namespace, prefix) { + prefix = prefix || ''; + return prefix + namespace.split('.').map(function (name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + }).join(''); +} +/** + * Returns a function, that, as long as it continues to be invoked, will not + * be triggered. The function will be called after it stops being called for + * N milliseconds. If `immediate` is passed, trigger the function on the + * leading edge, instead of the trailing. + * @param {Function} func + * @param {Number} wait + * @param {Boolean} immediate + * @return {Function} + */ + + +function debounce(func, wait, immediate) { + var timeout; + return function () { + var context = this; + var args = arguments; + + var later = function later() { + timeout = null; + + if (!immediate) { + func.apply(context, args); + } + }; + + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + + if (callNow) { + func.apply(context, args); + } + }; +} +/** + * + * @param {String} url + * @return {Boolean} + */ + + +function isValidUrl(url) { + var expression = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi; + return expression.test(url); +} + +/* harmony default export */ const func = ({ + eq: eq, + eq2: eq2, + peq2: peq2, + ok: ok, + fail: fail, + self: func_self, + not: not, + and: and, + invoke: invoke, + resetUniqueId: resetUniqueId, + uniqueId: uniqueId, + rect2bnd: rect2bnd, + invertObject: invertObject, + namespaceToCamel: namespaceToCamel, + debounce: debounce, + isValidUrl: isValidUrl +}); +;// CONCATENATED MODULE: ./src/js/core/lists.js + +/** + * returns the first item of an array. + * + * @param {Array} array + */ + +function head(array) { + return array[0]; +} +/** + * returns the last item of an array. + * + * @param {Array} array + */ + + +function last(array) { + return array[array.length - 1]; +} +/** + * returns everything but the last entry of the array. + * + * @param {Array} array + */ + + +function initial(array) { + return array.slice(0, array.length - 1); +} +/** + * returns the rest of the items in an array. + * + * @param {Array} array + */ + + +function tail(array) { + return array.slice(1); +} +/** + * returns item of array + */ + + +function find(array, pred) { + for (var idx = 0, len = array.length; idx < len; idx++) { + var item = array[idx]; + + if (pred(item)) { + return item; + } + } +} +/** + * returns true if all of the values in the array pass the predicate truth test. + */ + + +function lists_all(array, pred) { + for (var idx = 0, len = array.length; idx < len; idx++) { + if (!pred(array[idx])) { + return false; + } + } + + return true; +} +/** + * returns true if the value is present in the list. + */ + + +function contains(array, item) { + if (array && array.length && item) { + if (array.indexOf) { + return array.indexOf(item) !== -1; + } else if (array.contains) { + // `DOMTokenList` doesn't implement `.indexOf`, but it implements `.contains` + return array.contains(item); + } + } + + return false; +} +/** + * get sum from a list + * + * @param {Array} array - array + * @param {Function} fn - iterator + */ + + +function sum(array, fn) { + fn = fn || func.self; + return array.reduce(function (memo, v) { + return memo + fn(v); + }, 0); +} +/** + * returns a copy of the collection with array type. + * @param {Collection} collection - collection eg) node.childNodes, ... + */ + + +function from(collection) { + var result = []; + var length = collection.length; + var idx = -1; + + while (++idx < length) { + result[idx] = collection[idx]; + } + + return result; +} +/** + * returns whether list is empty or not + */ + + +function isEmpty(array) { + return !array || !array.length; +} +/** + * cluster elements by predicate function. + * + * @param {Array} array - array + * @param {Function} fn - predicate function for cluster rule + * @param {Array[]} + */ + + +function clusterBy(array, fn) { + if (!array.length) { + return []; + } + + var aTail = tail(array); + return aTail.reduce(function (memo, v) { + var aLast = last(memo); + + if (fn(last(aLast), v)) { + aLast[aLast.length] = v; + } else { + memo[memo.length] = [v]; + } + + return memo; + }, [[head(array)]]); +} +/** + * returns a copy of the array with all false values removed + * + * @param {Array} array - array + * @param {Function} fn - predicate function for cluster rule + */ + + +function compact(array) { + var aResult = []; + + for (var idx = 0, len = array.length; idx < len; idx++) { + if (array[idx]) { + aResult.push(array[idx]); + } + } + + return aResult; +} +/** + * produces a duplicate-free version of the array + * + * @param {Array} array + */ + + +function unique(array) { + var results = []; + + for (var idx = 0, len = array.length; idx < len; idx++) { + if (!contains(results, array[idx])) { + results.push(array[idx]); + } + } + + return results; +} +/** + * returns next item. + * @param {Array} array + */ + + +function next(array, item) { + if (array && array.length && item) { + var idx = array.indexOf(item); + return idx === -1 ? null : array[idx + 1]; + } + + return null; +} +/** + * returns prev item. + * @param {Array} array + */ + + +function prev(array, item) { + if (array && array.length && item) { + var idx = array.indexOf(item); + return idx === -1 ? null : array[idx - 1]; + } + + return null; +} +/** + * @class core.list + * + * list utils + * + * @singleton + * @alternateClassName list + */ + + +/* harmony default export */ const lists = ({ + head: head, + last: last, + initial: initial, + tail: tail, + prev: prev, + next: next, + find: find, + contains: contains, + all: lists_all, + sum: sum, + from: from, + isEmpty: isEmpty, + clusterBy: clusterBy, + compact: compact, + unique: unique +}); +;// CONCATENATED MODULE: ./src/js/core/dom.js + + + + +var NBSP_CHAR = String.fromCharCode(160); +var ZERO_WIDTH_NBSP_CHAR = "\uFEFF"; +/** + * @method isEditable + * + * returns whether node is `note-editable` or not. + * + * @param {Node} node + * @return {Boolean} + */ + +function isEditable(node) { + return node && external_jQuery_default()(node).hasClass('note-editable'); +} +/** + * @method isControlSizing + * + * returns whether node is `note-control-sizing` or not. + * + * @param {Node} node + * @return {Boolean} + */ + + +function isControlSizing(node) { + return node && external_jQuery_default()(node).hasClass('note-control-sizing'); +} +/** + * @method makePredByNodeName + * + * returns predicate which judge whether nodeName is same + * + * @param {String} nodeName + * @return {Function} + */ + + +function makePredByNodeName(nodeName) { + nodeName = nodeName.toUpperCase(); + return function (node) { + return node && node.nodeName.toUpperCase() === nodeName; + }; +} +/** + * @method isText + * + * + * + * @param {Node} node + * @return {Boolean} true if node's type is text(3) + */ + + +function isText(node) { + return node && node.nodeType === 3; +} +/** + * @method isElement + * + * + * + * @param {Node} node + * @return {Boolean} true if node's type is element(1) + */ + + +function isElement(node) { + return node && node.nodeType === 1; +} +/** + * ex) br, col, embed, hr, img, input, ... + * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements + */ + + +function isVoid(node) { + return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^AUDIO|^VIDEO|^EMBED/.test(node.nodeName.toUpperCase()); +} + +function isPara(node) { + if (isEditable(node)) { + return false; + } // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph + + + return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase()); +} + +function isHeading(node) { + return node && /^H[1-7]/.test(node.nodeName.toUpperCase()); +} + +var isPre = makePredByNodeName('PRE'); +var isLi = makePredByNodeName('LI'); + +function isPurePara(node) { + return isPara(node) && !isLi(node); +} + +var isTable = makePredByNodeName('TABLE'); +var isData = makePredByNodeName('DATA'); + +function isInline(node) { + return !isBodyContainer(node) && !isList(node) && !isHr(node) && !isPara(node) && !isTable(node) && !isBlockquote(node) && !isData(node); +} + +function isList(node) { + return node && /^UL|^OL/.test(node.nodeName.toUpperCase()); +} + +var isHr = makePredByNodeName('HR'); + +function isCell(node) { + return node && /^TD|^TH/.test(node.nodeName.toUpperCase()); +} + +var isBlockquote = makePredByNodeName('BLOCKQUOTE'); + +function isBodyContainer(node) { + return isCell(node) || isBlockquote(node) || isEditable(node); +} + +var isAnchor = makePredByNodeName('A'); + +function isParaInline(node) { + return isInline(node) && !!ancestor(node, isPara); +} + +function isBodyInline(node) { + return isInline(node) && !ancestor(node, isPara); +} + +var isBody = makePredByNodeName('BODY'); +/** + * returns whether nodeB is closest sibling of nodeA + * + * @param {Node} nodeA + * @param {Node} nodeB + * @return {Boolean} + */ + +function isClosestSibling(nodeA, nodeB) { + return nodeA.nextSibling === nodeB || nodeA.previousSibling === nodeB; +} +/** + * returns array of closest siblings with node + * + * @param {Node} node + * @param {function} [pred] - predicate function + * @return {Node[]} + */ + + +function withClosestSiblings(node, pred) { + pred = pred || func.ok; + var siblings = []; + + if (node.previousSibling && pred(node.previousSibling)) { + siblings.push(node.previousSibling); + } + + siblings.push(node); + + if (node.nextSibling && pred(node.nextSibling)) { + siblings.push(node.nextSibling); + } + + return siblings; +} +/** + * blank HTML for cursor position + * - [workaround] old IE only works with   + * - [workaround] IE11 and other browser works with bogus br + */ + + +var blankHTML = env.isMSIE && env.browserVersion < 11 ? ' ' : '
'; +/** + * @method nodeLength + * + * returns #text's text size or element's childNodes size + * + * @param {Node} node + */ + +function nodeLength(node) { + if (isText(node)) { + return node.nodeValue.length; + } + + if (node) { + return node.childNodes.length; + } + + return 0; +} +/** + * returns whether deepest child node is empty or not. + * + * @param {Node} node + * @return {Boolean} + */ + + +function deepestChildIsEmpty(node) { + do { + if (node.firstElementChild === null || node.firstElementChild.innerHTML === '') break; + } while (node = node.firstElementChild); + + return dom_isEmpty(node); +} +/** + * returns whether node is empty or not. + * + * @param {Node} node + * @return {Boolean} + */ + + +function dom_isEmpty(node) { + var len = nodeLength(node); + + if (len === 0) { + return true; + } else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) { + // ex)


,
+ return true; + } else if (lists.all(node.childNodes, isText) && node.innerHTML === '') { + // ex)

, + return true; + } + + return false; +} +/** + * padding blankHTML if node is empty (for cursor position) + */ + + +function paddingBlankHTML(node) { + if (!isVoid(node) && !nodeLength(node)) { + node.innerHTML = blankHTML; + } +} +/** + * find nearest ancestor predicate hit + * + * @param {Node} node + * @param {Function} pred - predicate function + */ + + +function ancestor(node, pred) { + while (node) { + if (pred(node)) { + return node; + } + + if (isEditable(node)) { + break; + } + + node = node.parentNode; + } + + return null; +} +/** + * find nearest ancestor only single child blood line and predicate hit + * + * @param {Node} node + * @param {Function} pred - predicate function + */ + + +function singleChildAncestor(node, pred) { + node = node.parentNode; + + while (node) { + if (nodeLength(node) !== 1) { + break; + } + + if (pred(node)) { + return node; + } + + if (isEditable(node)) { + break; + } + + node = node.parentNode; + } + + return null; +} +/** + * returns new array of ancestor nodes (until predicate hit). + * + * @param {Node} node + * @param {Function} [optional] pred - predicate function + */ + + +function listAncestor(node, pred) { + pred = pred || func.fail; + var ancestors = []; + ancestor(node, function (el) { + if (!isEditable(el)) { + ancestors.push(el); + } + + return pred(el); + }); + return ancestors; +} +/** + * find farthest ancestor predicate hit + */ + + +function lastAncestor(node, pred) { + var ancestors = listAncestor(node); + return lists.last(ancestors.filter(pred)); +} +/** + * returns common ancestor node between two nodes. + * + * @param {Node} nodeA + * @param {Node} nodeB + */ + + +function commonAncestor(nodeA, nodeB) { + var ancestors = listAncestor(nodeA); + + for (var n = nodeB; n; n = n.parentNode) { + if (ancestors.indexOf(n) > -1) return n; + } + + return null; // difference document area +} +/** + * listing all previous siblings (until predicate hit). + * + * @param {Node} node + * @param {Function} [optional] pred - predicate function + */ + + +function listPrev(node, pred) { + pred = pred || func.fail; + var nodes = []; + + while (node) { + if (pred(node)) { + break; + } + + nodes.push(node); + node = node.previousSibling; + } + + return nodes; +} +/** + * listing next siblings (until predicate hit). + * + * @param {Node} node + * @param {Function} [pred] - predicate function + */ + + +function listNext(node, pred) { + pred = pred || func.fail; + var nodes = []; + + while (node) { + if (pred(node)) { + break; + } + + nodes.push(node); + node = node.nextSibling; + } + + return nodes; +} +/** + * listing descendant nodes + * + * @param {Node} node + * @param {Function} [pred] - predicate function + */ + + +function listDescendant(node, pred) { + var descendants = []; + pred = pred || func.ok; // start DFS(depth first search) with node + + (function fnWalk(current) { + if (node !== current && pred(current)) { + descendants.push(current); + } + + for (var idx = 0, len = current.childNodes.length; idx < len; idx++) { + fnWalk(current.childNodes[idx]); + } + })(node); + + return descendants; +} +/** + * wrap node with new tag. + * + * @param {Node} node + * @param {Node} tagName of wrapper + * @return {Node} - wrapper + */ + + +function wrap(node, wrapperName) { + var parent = node.parentNode; + var wrapper = external_jQuery_default()('<' + wrapperName + '>')[0]; + parent.insertBefore(wrapper, node); + wrapper.appendChild(node); + return wrapper; +} +/** + * insert node after preceding + * + * @param {Node} node + * @param {Node} preceding - predicate function + */ + + +function insertAfter(node, preceding) { + var next = preceding.nextSibling; + var parent = preceding.parentNode; + + if (next) { + parent.insertBefore(node, next); + } else { + parent.appendChild(node); + } + + return node; +} +/** + * append elements. + * + * @param {Node} node + * @param {Collection} aChild + */ + + +function appendChildNodes(node, aChild) { + external_jQuery_default().each(aChild, function (idx, child) { + node.appendChild(child); + }); + return node; +} +/** + * returns whether boundaryPoint is left edge or not. + * + * @param {BoundaryPoint} point + * @return {Boolean} + */ + + +function isLeftEdgePoint(point) { + return point.offset === 0; +} +/** + * returns whether boundaryPoint is right edge or not. + * + * @param {BoundaryPoint} point + * @return {Boolean} + */ + + +function isRightEdgePoint(point) { + return point.offset === nodeLength(point.node); +} +/** + * returns whether boundaryPoint is edge or not. + * + * @param {BoundaryPoint} point + * @return {Boolean} + */ + + +function isEdgePoint(point) { + return isLeftEdgePoint(point) || isRightEdgePoint(point); +} +/** + * returns whether node is left edge of ancestor or not. + * + * @param {Node} node + * @param {Node} ancestor + * @return {Boolean} + */ + + +function isLeftEdgeOf(node, ancestor) { + while (node && node !== ancestor) { + if (position(node) !== 0) { + return false; + } + + node = node.parentNode; + } + + return true; +} +/** + * returns whether node is right edge of ancestor or not. + * + * @param {Node} node + * @param {Node} ancestor + * @return {Boolean} + */ + + +function isRightEdgeOf(node, ancestor) { + if (!ancestor) { + return false; + } + + while (node && node !== ancestor) { + if (position(node) !== nodeLength(node.parentNode) - 1) { + return false; + } + + node = node.parentNode; + } + + return true; +} +/** + * returns whether point is left edge of ancestor or not. + * @param {BoundaryPoint} point + * @param {Node} ancestor + * @return {Boolean} + */ + + +function isLeftEdgePointOf(point, ancestor) { + return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor); +} +/** + * returns whether point is right edge of ancestor or not. + * @param {BoundaryPoint} point + * @param {Node} ancestor + * @return {Boolean} + */ + + +function isRightEdgePointOf(point, ancestor) { + return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor); +} +/** + * returns offset from parent. + * + * @param {Node} node + */ + + +function position(node) { + var offset = 0; + + while (node = node.previousSibling) { + offset += 1; + } + + return offset; +} + +function hasChildren(node) { + return !!(node && node.childNodes && node.childNodes.length); +} +/** + * returns previous boundaryPoint + * + * @param {BoundaryPoint} point + * @param {Boolean} isSkipInnerOffset + * @return {BoundaryPoint} + */ + + +function prevPoint(point, isSkipInnerOffset) { + var node; + var offset; + + if (point.offset === 0) { + if (isEditable(point.node)) { + return null; + } + + node = point.node.parentNode; + offset = position(point.node); + } else if (hasChildren(point.node)) { + node = point.node.childNodes[point.offset - 1]; + offset = nodeLength(node); + } else { + node = point.node; + offset = isSkipInnerOffset ? 0 : point.offset - 1; + } + + return { + node: node, + offset: offset + }; +} +/** + * returns next boundaryPoint + * + * @param {BoundaryPoint} point + * @param {Boolean} isSkipInnerOffset + * @return {BoundaryPoint} + */ + + +function nextPoint(point, isSkipInnerOffset) { + var node, offset; + + if (nodeLength(point.node) === point.offset) { + if (isEditable(point.node)) { + return null; + } + + var nextTextNode = getNextTextNode(point.node); + + if (nextTextNode) { + node = nextTextNode; + offset = 0; + } else { + node = point.node.parentNode; + offset = position(point.node) + 1; + } + } else if (hasChildren(point.node)) { + node = point.node.childNodes[point.offset]; + offset = 0; + } else { + node = point.node; + offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1; + } + + return { + node: node, + offset: offset + }; +} +/** + * returns next boundaryPoint with empty node + * + * @param {BoundaryPoint} point + * @param {Boolean} isSkipInnerOffset + * @return {BoundaryPoint} + */ + + +function nextPointWithEmptyNode(point, isSkipInnerOffset) { + var node, + offset = 0; // if node is empty string node, return current node's sibling. + + if (dom_isEmpty(point.node)) { + if (point.node === null) { + return null; + } + + node = point.node.nextSibling; + offset = 0; + return { + node: node, + offset: offset + }; + } + + if (nodeLength(point.node) === point.offset) { + if (isEditable(point.node)) { + return null; + } + + node = point.node.parentNode; + offset = position(point.node) + 1; // if next node is editable , return current node's sibling node. + + if (isEditable(node)) { + node = point.node.nextSibling; + offset = 0; + } + } else if (hasChildren(point.node)) { + node = point.node.childNodes[point.offset]; + offset = 0; + + if (dom_isEmpty(node)) { + if (!dom_isEmpty(point.node.nextSibling)) { + return { + node: point.node.nextSibling, + offset: offset + }; + } + + return null; + } + } else { + node = point.node; + offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1; + + if (dom_isEmpty(node)) { + return null; + } + } + + return { + node: node, + offset: offset + }; +} +/* +* returns the next Text node index or 0 if not found. +*/ + + +function getNextTextNode(actual) { + if (!actual.nextSibling) return undefined; + if (actual.parent !== actual.nextSibling.parent) return undefined; + if (isText(actual.nextSibling)) return actual.nextSibling;else return getNextTextNode(actual.nextSibling); +} +/** + * returns whether pointA and pointB is same or not. + * + * @param {BoundaryPoint} pointA + * @param {BoundaryPoint} pointB + * @return {Boolean} + */ + + +function isSamePoint(pointA, pointB) { + return pointA.node === pointB.node && pointA.offset === pointB.offset; +} +/** + * returns whether point is visible (can set cursor) or not. + * + * @param {BoundaryPoint} point + * @return {Boolean} + */ + + +function isVisiblePoint(point) { + if (isText(point.node) || !hasChildren(point.node) || dom_isEmpty(point.node)) { + return true; + } + + var leftNode = point.node.childNodes[point.offset - 1]; + var rightNode = point.node.childNodes[point.offset]; + + if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode)) || isTable(rightNode)) { + return true; + } + + return false; +} +/** + * @method prevPointUtil + * + * @param {BoundaryPoint} point + * @param {Function} pred + * @return {BoundaryPoint} + */ + + +function prevPointUntil(point, pred) { + while (point) { + if (pred(point)) { + return point; + } + + point = prevPoint(point); + } + + return null; +} +/** + * @method nextPointUntil + * + * @param {BoundaryPoint} point + * @param {Function} pred + * @return {BoundaryPoint} + */ + + +function nextPointUntil(point, pred) { + while (point) { + if (pred(point)) { + return point; + } + + point = nextPoint(point); + } + + return null; +} +/** + * returns whether point has character or not. + * + * @param {Point} point + * @return {Boolean} + */ + + +function isCharPoint(point) { + if (!isText(point.node)) { + return false; + } + + var ch = point.node.nodeValue.charAt(point.offset - 1); + return ch && ch !== ' ' && ch !== NBSP_CHAR; +} +/** + * returns whether point has space or not. + * + * @param {Point} point + * @return {Boolean} + */ + + +function isSpacePoint(point) { + if (!isText(point.node)) { + return false; + } + + var ch = point.node.nodeValue.charAt(point.offset - 1); + return ch === ' ' || ch === NBSP_CHAR; +} +/** + * @method walkPoint + * + * @param {BoundaryPoint} startPoint + * @param {BoundaryPoint} endPoint + * @param {Function} handler + * @param {Boolean} isSkipInnerOffset + */ + + +function walkPoint(startPoint, endPoint, handler, isSkipInnerOffset) { + var point = startPoint; + + while (point) { + handler(point); + + if (isSamePoint(point, endPoint)) { + break; + } + + var isSkipOffset = isSkipInnerOffset && startPoint.node !== point.node && endPoint.node !== point.node; + point = nextPointWithEmptyNode(point, isSkipOffset); + } +} +/** + * @method makeOffsetPath + * + * return offsetPath(array of offset) from ancestor + * + * @param {Node} ancestor - ancestor node + * @param {Node} node + */ + + +function makeOffsetPath(ancestor, node) { + var ancestors = listAncestor(node, func.eq(ancestor)); + return ancestors.map(position).reverse(); +} +/** + * @method fromOffsetPath + * + * return element from offsetPath(array of offset) + * + * @param {Node} ancestor - ancestor node + * @param {array} offsets - offsetPath + */ + + +function fromOffsetPath(ancestor, offsets) { + var current = ancestor; + + for (var i = 0, len = offsets.length; i < len; i++) { + if (current.childNodes.length <= offsets[i]) { + current = current.childNodes[current.childNodes.length - 1]; + } else { + current = current.childNodes[offsets[i]]; + } + } + + return current; +} +/** + * @method splitNode + * + * split element or #text + * + * @param {BoundaryPoint} point + * @param {Object} [options] + * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false + * @param {Boolean} [options.isNotSplitEdgePoint] - default: false + * @param {Boolean} [options.isDiscardEmptySplits] - default: false + * @return {Node} right node of boundaryPoint + */ + + +function splitNode(point, options) { + var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML; + var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint; + var isDiscardEmptySplits = options && options.isDiscardEmptySplits; + + if (isDiscardEmptySplits) { + isSkipPaddingBlankHTML = true; + } // edge case + + + if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) { + if (isLeftEdgePoint(point)) { + return point.node; + } else if (isRightEdgePoint(point)) { + return point.node.nextSibling; + } + } // split #text + + + if (isText(point.node)) { + return point.node.splitText(point.offset); + } else { + var childNode = point.node.childNodes[point.offset]; + var clone = insertAfter(point.node.cloneNode(false), point.node); + appendChildNodes(clone, listNext(childNode)); + + if (!isSkipPaddingBlankHTML) { + paddingBlankHTML(point.node); + paddingBlankHTML(clone); + } + + if (isDiscardEmptySplits) { + if (dom_isEmpty(point.node)) { + remove(point.node); + } + + if (dom_isEmpty(clone)) { + remove(clone); + return point.node.nextSibling; + } + } + + return clone; + } +} +/** + * @method splitTree + * + * split tree by point + * + * @param {Node} root - split root + * @param {BoundaryPoint} point + * @param {Object} [options] + * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false + * @param {Boolean} [options.isNotSplitEdgePoint] - default: false + * @return {Node} right node of boundaryPoint + */ + + +function splitTree(root, point, options) { + // ex) [#text, ,

] + var ancestors = listAncestor(point.node, func.eq(root)); + + if (!ancestors.length) { + return null; + } else if (ancestors.length === 1) { + return splitNode(point, options); + } + + return ancestors.reduce(function (node, parent) { + if (node === point.node) { + node = splitNode(point, options); + } + + return splitNode({ + node: parent, + offset: node ? position(node) : nodeLength(parent) + }, options); + }); +} +/** + * split point + * + * @param {Point} point + * @param {Boolean} isInline + * @return {Object} + */ + + +function splitPoint(point, isInline) { + // find splitRoot, container + // - inline: splitRoot is a child of paragraph + // - block: splitRoot is a child of bodyContainer + var pred = isInline ? isPara : isBodyContainer; + var ancestors = listAncestor(point.node, pred); + var topAncestor = lists.last(ancestors) || point.node; + var splitRoot, container; + + if (pred(topAncestor)) { + splitRoot = ancestors[ancestors.length - 2]; + container = topAncestor; + } else { + splitRoot = topAncestor; + container = splitRoot.parentNode; + } // if splitRoot is exists, split with splitTree + + + var pivot = splitRoot && splitTree(splitRoot, point, { + isSkipPaddingBlankHTML: isInline, + isNotSplitEdgePoint: isInline + }); // if container is point.node, find pivot with point.offset + + if (!pivot && container === point.node) { + pivot = point.node.childNodes[point.offset]; + } + + return { + rightNode: pivot, + container: container + }; +} + +function create(nodeName) { + return document.createElement(nodeName); +} + +function createText(text) { + return document.createTextNode(text); +} +/** + * @method remove + * + * remove node, (isRemoveChild: remove child or not) + * + * @param {Node} node + * @param {Boolean} isRemoveChild + */ + + +function remove(node, isRemoveChild) { + if (!node || !node.parentNode) { + return; + } + + if (node.removeNode) { + return node.removeNode(isRemoveChild); + } + + var parent = node.parentNode; + + if (!isRemoveChild) { + var nodes = []; + + for (var i = 0, len = node.childNodes.length; i < len; i++) { + nodes.push(node.childNodes[i]); + } + + for (var _i = 0, _len = nodes.length; _i < _len; _i++) { + parent.insertBefore(nodes[_i], node); + } + } + + parent.removeChild(node); +} +/** + * @method removeWhile + * + * @param {Node} node + * @param {Function} pred + */ + + +function removeWhile(node, pred) { + while (node) { + if (isEditable(node) || !pred(node)) { + break; + } + + var parent = node.parentNode; + remove(node); + node = parent; + } +} +/** + * @method replace + * + * replace node with provided nodeName + * + * @param {Node} node + * @param {String} nodeName + * @return {Node} - new node + */ + + +function replace(node, nodeName) { + if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) { + return node; + } + + var newNode = create(nodeName); + + if (node.style.cssText) { + newNode.style.cssText = node.style.cssText; + } + + appendChildNodes(newNode, lists.from(node.childNodes)); + insertAfter(newNode, node); + remove(node); + return newNode; +} + +var isTextarea = makePredByNodeName('TEXTAREA'); +/** + * @param {jQuery} $node + * @param {Boolean} [stripLinebreaks] - default: false + */ + +function value($node, stripLinebreaks) { + var val = isTextarea($node[0]) ? $node.val() : $node.html(); + + if (stripLinebreaks) { + return val.replace(/[\n\r]/g, ''); + } + + return val; +} +/** + * @method html + * + * get the HTML contents of node + * + * @param {jQuery} $node + * @param {Boolean} [isNewlineOnBlock] + */ + + +function html($node, isNewlineOnBlock) { + var markup = value($node); + + if (isNewlineOnBlock) { + var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g; + markup = markup.replace(regexTag, function (match, endSlash, name) { + name = name.toUpperCase(); + var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) && !!endSlash; + var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name); + return match + (isEndOfInlineContainer || isBlockNode ? '\n' : ''); + }); + markup = markup.trim(); + } + + return markup; +} + +function posFromPlaceholder(placeholder) { + var $placeholder = external_jQuery_default()(placeholder); + var pos = $placeholder.offset(); + var height = $placeholder.outerHeight(true); // include margin + + return { + left: pos.left, + top: pos.top + height + }; +} + +function attachEvents($node, events) { + Object.keys(events).forEach(function (key) { + $node.on(key, events[key]); + }); +} + +function detachEvents($node, events) { + Object.keys(events).forEach(function (key) { + $node.off(key, events[key]); + }); +} +/** + * @method isCustomStyleTag + * + * assert if a node contains a "note-styletag" class, + * which implies that's a custom-made style tag node + * + * @param {Node} an HTML DOM node + */ + + +function isCustomStyleTag(node) { + return node && !isText(node) && lists.contains(node.classList, 'note-styletag'); +} + +/* harmony default export */ const dom = ({ + /** @property {String} NBSP_CHAR */ + NBSP_CHAR: NBSP_CHAR, + + /** @property {String} ZERO_WIDTH_NBSP_CHAR */ + ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR, + + /** @property {String} blank */ + blank: blankHTML, + + /** @property {String} emptyPara */ + emptyPara: "

".concat(blankHTML, "

"), + makePredByNodeName: makePredByNodeName, + isEditable: isEditable, + isControlSizing: isControlSizing, + isText: isText, + isElement: isElement, + isVoid: isVoid, + isPara: isPara, + isPurePara: isPurePara, + isHeading: isHeading, + isInline: isInline, + isBlock: func.not(isInline), + isBodyInline: isBodyInline, + isBody: isBody, + isParaInline: isParaInline, + isPre: isPre, + isList: isList, + isTable: isTable, + isData: isData, + isCell: isCell, + isBlockquote: isBlockquote, + isBodyContainer: isBodyContainer, + isAnchor: isAnchor, + isDiv: makePredByNodeName('DIV'), + isLi: isLi, + isBR: makePredByNodeName('BR'), + isSpan: makePredByNodeName('SPAN'), + isB: makePredByNodeName('B'), + isU: makePredByNodeName('U'), + isS: makePredByNodeName('S'), + isI: makePredByNodeName('I'), + isImg: makePredByNodeName('IMG'), + isTextarea: isTextarea, + deepestChildIsEmpty: deepestChildIsEmpty, + isEmpty: dom_isEmpty, + isEmptyAnchor: func.and(isAnchor, dom_isEmpty), + isClosestSibling: isClosestSibling, + withClosestSiblings: withClosestSiblings, + nodeLength: nodeLength, + isLeftEdgePoint: isLeftEdgePoint, + isRightEdgePoint: isRightEdgePoint, + isEdgePoint: isEdgePoint, + isLeftEdgeOf: isLeftEdgeOf, + isRightEdgeOf: isRightEdgeOf, + isLeftEdgePointOf: isLeftEdgePointOf, + isRightEdgePointOf: isRightEdgePointOf, + prevPoint: prevPoint, + nextPoint: nextPoint, + nextPointWithEmptyNode: nextPointWithEmptyNode, + isSamePoint: isSamePoint, + isVisiblePoint: isVisiblePoint, + prevPointUntil: prevPointUntil, + nextPointUntil: nextPointUntil, + isCharPoint: isCharPoint, + isSpacePoint: isSpacePoint, + walkPoint: walkPoint, + ancestor: ancestor, + singleChildAncestor: singleChildAncestor, + listAncestor: listAncestor, + lastAncestor: lastAncestor, + listNext: listNext, + listPrev: listPrev, + listDescendant: listDescendant, + commonAncestor: commonAncestor, + wrap: wrap, + insertAfter: insertAfter, + appendChildNodes: appendChildNodes, + position: position, + hasChildren: hasChildren, + makeOffsetPath: makeOffsetPath, + fromOffsetPath: fromOffsetPath, + splitTree: splitTree, + splitPoint: splitPoint, + create: create, + createText: createText, + remove: remove, + removeWhile: removeWhile, + replace: replace, + html: html, + value: value, + posFromPlaceholder: posFromPlaceholder, + attachEvents: attachEvents, + detachEvents: detachEvents, + isCustomStyleTag: isCustomStyleTag +}); +;// CONCATENATED MODULE: ./src/js/Context.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; } + + + + + + +var Context = /*#__PURE__*/function () { + /** + * @param {jQuery} $note + * @param {Object} options + */ + function Context($note, options) { + _classCallCheck(this, Context); + + this.$note = $note; + this.memos = {}; + this.modules = {}; + this.layoutInfo = {}; + this.options = external_jQuery_default().extend(true, {}, options); // init ui with options + + (external_jQuery_default()).summernote.ui = external_jQuery_default().summernote.ui_template(this.options); + this.ui = (external_jQuery_default()).summernote.ui; + this.initialize(); + } + /** + * create layout and initialize modules and other resources + */ + + + _createClass(Context, [{ + key: "initialize", + value: function initialize() { + this.layoutInfo = this.ui.createLayout(this.$note); + + this._initialize(); + + this.$note.hide(); + return this; + } + /** + * destroy modules and other resources and remove layout + */ + + }, { + key: "destroy", + value: function destroy() { + this._destroy(); + + this.$note.removeData('summernote'); + this.ui.removeLayout(this.$note, this.layoutInfo); + } + /** + * destory modules and other resources and initialize it again + */ + + }, { + key: "reset", + value: function reset() { + var disabled = this.isDisabled(); + this.code(dom.emptyPara); + + this._destroy(); + + this._initialize(); + + if (disabled) { + this.disable(); + } + } + }, { + key: "_initialize", + value: function _initialize() { + var _this = this; + + // set own id + this.options.id = func.uniqueId(external_jQuery_default().now()); // set default container for tooltips, popovers, and dialogs + + this.options.container = this.options.container || this.layoutInfo.editor; // add optional buttons + + var buttons = external_jQuery_default().extend({}, this.options.buttons); + Object.keys(buttons).forEach(function (key) { + _this.memo('button.' + key, buttons[key]); + }); + var modules = external_jQuery_default().extend({}, this.options.modules, (external_jQuery_default()).summernote.plugins || {}); // add and initialize modules + + Object.keys(modules).forEach(function (key) { + _this.module(key, modules[key], true); + }); + Object.keys(this.modules).forEach(function (key) { + _this.initializeModule(key); + }); + } + }, { + key: "_destroy", + value: function _destroy() { + var _this2 = this; + + // destroy modules with reversed order + Object.keys(this.modules).reverse().forEach(function (key) { + _this2.removeModule(key); + }); + Object.keys(this.memos).forEach(function (key) { + _this2.removeMemo(key); + }); // trigger custom onDestroy callback + + this.triggerEvent('destroy', this); + } + }, { + key: "code", + value: function code(html) { + var isActivated = this.invoke('codeview.isActivated'); + + if (html === undefined) { + this.invoke('codeview.sync'); + return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html(); + } else { + if (isActivated) { + this.invoke('codeview.sync', html); + } else { + this.layoutInfo.editable.html(html); + } + + this.$note.val(html); + this.triggerEvent('change', html, this.layoutInfo.editable); + } + } + }, { + key: "isDisabled", + value: function isDisabled() { + return this.layoutInfo.editable.attr('contenteditable') === 'false'; + } + }, { + key: "enable", + value: function enable() { + this.layoutInfo.editable.attr('contenteditable', true); + this.invoke('toolbar.activate', true); + this.triggerEvent('disable', false); + this.options.editing = true; + } + }, { + key: "disable", + value: function disable() { + // close codeview if codeview is opend + if (this.invoke('codeview.isActivated')) { + this.invoke('codeview.deactivate'); + } + + this.layoutInfo.editable.attr('contenteditable', false); + this.options.editing = false; + this.invoke('toolbar.deactivate', true); + this.triggerEvent('disable', true); + } + }, { + key: "triggerEvent", + value: function triggerEvent() { + var namespace = lists.head(arguments); + var args = lists.tail(lists.from(arguments)); + var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')]; + + if (callback) { + callback.apply(this.$note[0], args); + } + + this.$note.trigger('summernote.' + namespace, args); + } + }, { + key: "initializeModule", + value: function initializeModule(key) { + var module = this.modules[key]; + module.shouldInitialize = module.shouldInitialize || func.ok; + + if (!module.shouldInitialize()) { + return; + } // initialize module + + + if (module.initialize) { + module.initialize(); + } // attach events + + + if (module.events) { + dom.attachEvents(this.$note, module.events); + } + } + }, { + key: "module", + value: function module(key, ModuleClass, withoutIntialize) { + if (arguments.length === 1) { + return this.modules[key]; + } + + this.modules[key] = new ModuleClass(this); + + if (!withoutIntialize) { + this.initializeModule(key); + } + } + }, { + key: "removeModule", + value: function removeModule(key) { + var module = this.modules[key]; + + if (module.shouldInitialize()) { + if (module.events) { + dom.detachEvents(this.$note, module.events); + } + + if (module.destroy) { + module.destroy(); + } + } + + delete this.modules[key]; + } + }, { + key: "memo", + value: function memo(key, obj) { + if (arguments.length === 1) { + return this.memos[key]; + } + + this.memos[key] = obj; + } + }, { + key: "removeMemo", + value: function removeMemo(key) { + if (this.memos[key] && this.memos[key].destroy) { + this.memos[key].destroy(); + } + + delete this.memos[key]; + } + /** + * Some buttons need to change their visual style immediately once they get pressed + */ + + }, { + key: "createInvokeHandlerAndUpdateState", + value: function createInvokeHandlerAndUpdateState(namespace, value) { + var _this3 = this; + + return function (event) { + _this3.createInvokeHandler(namespace, value)(event); + + _this3.invoke('buttons.updateCurrentStyle'); + }; + } + }, { + key: "createInvokeHandler", + value: function createInvokeHandler(namespace, value) { + var _this4 = this; + + return function (event) { + event.preventDefault(); + var $target = external_jQuery_default()(event.target); + + _this4.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target); + }; + } + }, { + key: "invoke", + value: function invoke() { + var namespace = lists.head(arguments); + var args = lists.tail(lists.from(arguments)); + var splits = namespace.split('.'); + var hasSeparator = splits.length > 1; + var moduleName = hasSeparator && lists.head(splits); + var methodName = hasSeparator ? lists.last(splits) : lists.head(splits); + var module = this.modules[moduleName || 'editor']; + + if (!moduleName && this[methodName]) { + return this[methodName].apply(this, args); + } else if (module && module[methodName] && module.shouldInitialize()) { + return module[methodName].apply(module, args); + } + } + }]); + + return Context; +}(); + + +;// CONCATENATED MODULE: ./src/js/summernote.js + + + + +external_jQuery_default().fn.extend({ + /** + * Summernote API + * + * @param {Object|String} + * @return {this} + */ + summernote: function summernote() { + var type = external_jQuery_default().type(lists.head(arguments)); + var isExternalAPICalled = type === 'string'; + var hasInitOptions = type === 'object'; + var options = external_jQuery_default().extend({}, (external_jQuery_default()).summernote.options, hasInitOptions ? lists.head(arguments) : {}); // Update options + + options.langInfo = external_jQuery_default().extend(true, {}, (external_jQuery_default()).summernote.lang["en-US"], (external_jQuery_default()).summernote.lang[options.lang]); + options.icons = external_jQuery_default().extend(true, {}, (external_jQuery_default()).summernote.options.icons, options.icons); + options.tooltip = options.tooltip === 'auto' ? !env.isSupportTouch : options.tooltip; + this.each(function (idx, note) { + var $note = external_jQuery_default()(note); + + if (!$note.data('summernote')) { + var context = new Context($note, options); + $note.data('summernote', context); + $note.data('summernote').triggerEvent('init', context.layoutInfo); + } + }); + var $note = this.first(); + + if ($note.length) { + var context = $note.data('summernote'); + + if (isExternalAPICalled) { + return context.invoke.apply(context, lists.from(arguments)); + } else if (options.focus) { + context.invoke('editor.focus'); + } + } + + return this; + } +}); +;// CONCATENATED MODULE: ./src/js/core/range.js +function range_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function range_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 range_createClass(Constructor, protoProps, staticProps) { if (protoProps) range_defineProperties(Constructor.prototype, protoProps); if (staticProps) range_defineProperties(Constructor, staticProps); return Constructor; } + + + + + + +/** + * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js + * + * @param {TextRange} textRange + * @param {Boolean} isStart + * @return {BoundaryPoint} + * + * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx + */ + +function textRangeToPoint(textRange, isStart) { + var container = textRange.parentElement(); + var offset; + var tester = document.body.createTextRange(); + var prevContainer; + var childNodes = lists.from(container.childNodes); + + for (offset = 0; offset < childNodes.length; offset++) { + if (dom.isText(childNodes[offset])) { + continue; + } + + tester.moveToElementText(childNodes[offset]); + + if (tester.compareEndPoints('StartToStart', textRange) >= 0) { + break; + } + + prevContainer = childNodes[offset]; + } + + if (offset !== 0 && dom.isText(childNodes[offset - 1])) { + var textRangeStart = document.body.createTextRange(); + var curTextNode = null; + textRangeStart.moveToElementText(prevContainer || container); + textRangeStart.collapse(!prevContainer); + curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild; + var pointTester = textRange.duplicate(); + pointTester.setEndPoint('StartToStart', textRangeStart); + var textCount = pointTester.text.replace(/[\r\n]/g, '').length; + + while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) { + textCount -= curTextNode.nodeValue.length; + curTextNode = curTextNode.nextSibling; + } // [workaround] enforce IE to re-reference curTextNode, hack + + + var dummy = curTextNode.nodeValue; // eslint-disable-line + + if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) && textCount === curTextNode.nodeValue.length) { + textCount -= curTextNode.nodeValue.length; + curTextNode = curTextNode.nextSibling; + } + + container = curTextNode; + offset = textCount; + } + + return { + cont: container, + offset: offset + }; +} +/** + * return TextRange from boundary point (inspired by google closure-library) + * @param {BoundaryPoint} point + * @return {TextRange} + */ + + +function pointToTextRange(point) { + var textRangeInfo = function textRangeInfo(container, offset) { + var node, isCollapseToStart; + + if (dom.isText(container)) { + var prevTextNodes = dom.listPrev(container, func.not(dom.isText)); + var prevContainer = lists.last(prevTextNodes).previousSibling; + node = prevContainer || container.parentNode; + offset += lists.sum(lists.tail(prevTextNodes), dom.nodeLength); + isCollapseToStart = !prevContainer; + } else { + node = container.childNodes[offset] || container; + + if (dom.isText(node)) { + return textRangeInfo(node, 0); + } + + offset = 0; + isCollapseToStart = false; + } + + return { + node: node, + collapseToStart: isCollapseToStart, + offset: offset + }; + }; + + var textRange = document.body.createTextRange(); + var info = textRangeInfo(point.node, point.offset); + textRange.moveToElementText(info.node); + textRange.collapse(info.collapseToStart); + textRange.moveStart('character', info.offset); + return textRange; +} +/** + * Wrapped Range + * + * @constructor + * @param {Node} sc - start container + * @param {Number} so - start offset + * @param {Node} ec - end container + * @param {Number} eo - end offset + */ + + +var WrappedRange = /*#__PURE__*/function () { + function WrappedRange(sc, so, ec, eo) { + range_classCallCheck(this, WrappedRange); + + this.sc = sc; + this.so = so; + this.ec = ec; + this.eo = eo; // isOnEditable: judge whether range is on editable or not + + this.isOnEditable = this.makeIsOn(dom.isEditable); // isOnList: judge whether range is on list node or not + + this.isOnList = this.makeIsOn(dom.isList); // isOnAnchor: judge whether range is on anchor node or not + + this.isOnAnchor = this.makeIsOn(dom.isAnchor); // isOnCell: judge whether range is on cell node or not + + this.isOnCell = this.makeIsOn(dom.isCell); // isOnData: judge whether range is on data node or not + + this.isOnData = this.makeIsOn(dom.isData); + } // nativeRange: get nativeRange from sc, so, ec, eo + + + range_createClass(WrappedRange, [{ + key: "nativeRange", + value: function nativeRange() { + if (env.isW3CRangeSupport) { + var w3cRange = document.createRange(); + w3cRange.setStart(this.sc, this.so); + w3cRange.setEnd(this.ec, this.eo); + return w3cRange; + } else { + var textRange = pointToTextRange({ + node: this.sc, + offset: this.so + }); + textRange.setEndPoint('EndToEnd', pointToTextRange({ + node: this.ec, + offset: this.eo + })); + return textRange; + } + } + }, { + key: "getPoints", + value: function getPoints() { + return { + sc: this.sc, + so: this.so, + ec: this.ec, + eo: this.eo + }; + } + }, { + key: "getStartPoint", + value: function getStartPoint() { + return { + node: this.sc, + offset: this.so + }; + } + }, { + key: "getEndPoint", + value: function getEndPoint() { + return { + node: this.ec, + offset: this.eo + }; + } + /** + * select update visible range + */ + + }, { + key: "select", + value: function select() { + var nativeRng = this.nativeRange(); + + if (env.isW3CRangeSupport) { + var selection = document.getSelection(); + + if (selection.rangeCount > 0) { + selection.removeAllRanges(); + } + + selection.addRange(nativeRng); + } else { + nativeRng.select(); + } + + return this; + } + /** + * Moves the scrollbar to start container(sc) of current range + * + * @return {WrappedRange} + */ + + }, { + key: "scrollIntoView", + value: function scrollIntoView(container) { + var height = external_jQuery_default()(container).height(); + + if (container.scrollTop + height < this.sc.offsetTop) { + container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop); + } + + return this; + } + /** + * @return {WrappedRange} + */ + + }, { + key: "normalize", + value: function normalize() { + /** + * @param {BoundaryPoint} point + * @param {Boolean} isLeftToRight - true: prefer to choose right node + * - false: prefer to choose left node + * @return {BoundaryPoint} + */ + var getVisiblePoint = function getVisiblePoint(point, isLeftToRight) { + if (!point) { + return point; + } // Just use the given point [XXX:Adhoc] + // - case 01. if the point is on the middle of the node + // - case 02. if the point is on the right edge and prefer to choose left node + // - case 03. if the point is on the left edge and prefer to choose right node + // - case 04. if the point is on the right edge and prefer to choose right node but the node is void + // - case 05. if the point is on the left edge and prefer to choose left node but the node is void + // - case 06. if the point is on the block node and there is no children + + + if (dom.isVisiblePoint(point)) { + if (!dom.isEdgePoint(point) || dom.isRightEdgePoint(point) && !isLeftToRight || dom.isLeftEdgePoint(point) && isLeftToRight || dom.isRightEdgePoint(point) && isLeftToRight && dom.isVoid(point.node.nextSibling) || dom.isLeftEdgePoint(point) && !isLeftToRight && dom.isVoid(point.node.previousSibling) || dom.isBlock(point.node) && dom.isEmpty(point.node)) { + return point; + } + } // point on block's edge + + + var block = dom.ancestor(point.node, dom.isBlock); + var hasRightNode = false; + + if (!hasRightNode) { + var prevPoint = dom.prevPoint(point) || { + node: null + }; + hasRightNode = (dom.isLeftEdgePointOf(point, block) || dom.isVoid(prevPoint.node)) && !isLeftToRight; + } + + var hasLeftNode = false; + + if (!hasLeftNode) { + var _nextPoint = dom.nextPoint(point) || { + node: null + }; + + hasLeftNode = (dom.isRightEdgePointOf(point, block) || dom.isVoid(_nextPoint.node)) && isLeftToRight; + } + + if (hasRightNode || hasLeftNode) { + // returns point already on visible point + if (dom.isVisiblePoint(point)) { + return point; + } // reverse direction + + + isLeftToRight = !isLeftToRight; + } + + var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint) : dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint); + return nextPoint || point; + }; + + var endPoint = getVisiblePoint(this.getEndPoint(), false); + var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true); + return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); + } + /** + * returns matched nodes on range + * + * @param {Function} [pred] - predicate function + * @param {Object} [options] + * @param {Boolean} [options.includeAncestor] + * @param {Boolean} [options.fullyContains] + * @return {Node[]} + */ + + }, { + key: "nodes", + value: function nodes(pred, options) { + pred = pred || func.ok; + var includeAncestor = options && options.includeAncestor; + var fullyContains = options && options.fullyContains; // TODO compare points and sort + + var startPoint = this.getStartPoint(); + var endPoint = this.getEndPoint(); + var nodes = []; + var leftEdgeNodes = []; + dom.walkPoint(startPoint, endPoint, function (point) { + if (dom.isEditable(point.node)) { + return; + } + + var node; + + if (fullyContains) { + if (dom.isLeftEdgePoint(point)) { + leftEdgeNodes.push(point.node); + } + + if (dom.isRightEdgePoint(point) && lists.contains(leftEdgeNodes, point.node)) { + node = point.node; + } + } else if (includeAncestor) { + node = dom.ancestor(point.node, pred); + } else { + node = point.node; + } + + if (node && pred(node)) { + nodes.push(node); + } + }, true); + return lists.unique(nodes); + } + /** + * returns commonAncestor of range + * @return {Element} - commonAncestor + */ + + }, { + key: "commonAncestor", + value: function commonAncestor() { + return dom.commonAncestor(this.sc, this.ec); + } + /** + * returns expanded range by pred + * + * @param {Function} pred - predicate function + * @return {WrappedRange} + */ + + }, { + key: "expand", + value: function expand(pred) { + var startAncestor = dom.ancestor(this.sc, pred); + var endAncestor = dom.ancestor(this.ec, pred); + + if (!startAncestor && !endAncestor) { + return new WrappedRange(this.sc, this.so, this.ec, this.eo); + } + + var boundaryPoints = this.getPoints(); + + if (startAncestor) { + boundaryPoints.sc = startAncestor; + boundaryPoints.so = 0; + } + + if (endAncestor) { + boundaryPoints.ec = endAncestor; + boundaryPoints.eo = dom.nodeLength(endAncestor); + } + + return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo); + } + /** + * @param {Boolean} isCollapseToStart + * @return {WrappedRange} + */ + + }, { + key: "collapse", + value: function collapse(isCollapseToStart) { + if (isCollapseToStart) { + return new WrappedRange(this.sc, this.so, this.sc, this.so); + } else { + return new WrappedRange(this.ec, this.eo, this.ec, this.eo); + } + } + /** + * splitText on range + */ + + }, { + key: "splitText", + value: function splitText() { + var isSameContainer = this.sc === this.ec; + var boundaryPoints = this.getPoints(); + + if (dom.isText(this.ec) && !dom.isEdgePoint(this.getEndPoint())) { + this.ec.splitText(this.eo); + } + + if (dom.isText(this.sc) && !dom.isEdgePoint(this.getStartPoint())) { + boundaryPoints.sc = this.sc.splitText(this.so); + boundaryPoints.so = 0; + + if (isSameContainer) { + boundaryPoints.ec = boundaryPoints.sc; + boundaryPoints.eo = this.eo - this.so; + } + } + + return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo); + } + /** + * delete contents on range + * @return {WrappedRange} + */ + + }, { + key: "deleteContents", + value: function deleteContents() { + if (this.isCollapsed()) { + return this; + } + + var rng = this.splitText(); + var nodes = rng.nodes(null, { + fullyContains: true + }); // find new cursor point + + var point = dom.prevPointUntil(rng.getStartPoint(), function (point) { + return !lists.contains(nodes, point.node); + }); + var emptyParents = []; + external_jQuery_default().each(nodes, function (idx, node) { + // find empty parents + var parent = node.parentNode; + + if (point.node !== parent && dom.nodeLength(parent) === 1) { + emptyParents.push(parent); + } + + dom.remove(node, false); + }); // remove empty parents + + external_jQuery_default().each(emptyParents, function (idx, node) { + dom.remove(node, false); + }); + return new WrappedRange(point.node, point.offset, point.node, point.offset).normalize(); + } + /** + * makeIsOn: return isOn(pred) function + */ + + }, { + key: "makeIsOn", + value: function makeIsOn(pred) { + return function () { + var ancestor = dom.ancestor(this.sc, pred); + return !!ancestor && ancestor === dom.ancestor(this.ec, pred); + }; + } + /** + * @param {Function} pred + * @return {Boolean} + */ + + }, { + key: "isLeftEdgeOf", + value: function isLeftEdgeOf(pred) { + if (!dom.isLeftEdgePoint(this.getStartPoint())) { + return false; + } + + var node = dom.ancestor(this.sc, pred); + return node && dom.isLeftEdgeOf(this.sc, node); + } + /** + * returns whether range was collapsed or not + */ + + }, { + key: "isCollapsed", + value: function isCollapsed() { + return this.sc === this.ec && this.so === this.eo; + } + /** + * wrap inline nodes which children of body with paragraph + * + * @return {WrappedRange} + */ + + }, { + key: "wrapBodyInlineWithPara", + value: function wrapBodyInlineWithPara() { + if (dom.isBodyContainer(this.sc) && dom.isEmpty(this.sc)) { + this.sc.innerHTML = dom.emptyPara; + return new WrappedRange(this.sc.firstChild, 0, this.sc.firstChild, 0); + } + /** + * [workaround] firefox often create range on not visible point. so normalize here. + * - firefox: |

text

| + * - chrome:

|text|

+ */ + + + var rng = this.normalize(); + + if (dom.isParaInline(this.sc) || dom.isPara(this.sc)) { + return rng; + } // find inline top ancestor + + + var topAncestor; + + if (dom.isInline(rng.sc)) { + var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline)); + topAncestor = lists.last(ancestors); + + if (!dom.isInline(topAncestor)) { + topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so]; + } + } else { + topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0]; + } + + if (topAncestor) { + // siblings not in paragraph + var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse(); + inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline)); // wrap with paragraph + + if (inlineSiblings.length) { + var para = dom.wrap(lists.head(inlineSiblings), 'p'); + dom.appendChildNodes(para, lists.tail(inlineSiblings)); + } + } + + return this.normalize(); + } + /** + * insert node at current cursor + * + * @param {Node} node + * @return {Node} + */ + + }, { + key: "insertNode", + value: function insertNode(node) { + var rng = this; + + if (dom.isText(node) || dom.isInline(node)) { + rng = this.wrapBodyInlineWithPara().deleteContents(); + } + + var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node)); + + if (info.rightNode) { + info.rightNode.parentNode.insertBefore(node, info.rightNode); + + if (dom.isEmpty(info.rightNode) && dom.isPara(node)) { + info.rightNode.parentNode.removeChild(info.rightNode); + } + } else { + info.container.appendChild(node); + } + + return node; + } + /** + * insert html at current cursor + */ + + }, { + key: "pasteHTML", + value: function pasteHTML(markup) { + markup = external_jQuery_default().trim(markup); + var contentsContainer = external_jQuery_default()('
').html(markup)[0]; + var childNodes = lists.from(contentsContainer.childNodes); // const rng = this.wrapBodyInlineWithPara().deleteContents(); + + var rng = this; + var reversed = false; + + if (rng.so >= 0) { + childNodes = childNodes.reverse(); + reversed = true; + } + + childNodes = childNodes.map(function (childNode) { + return rng.insertNode(childNode); + }); + + if (reversed) { + childNodes = childNodes.reverse(); + } + + return childNodes; + } + /** + * returns text in range + * + * @return {String} + */ + + }, { + key: "toString", + value: function toString() { + var nativeRng = this.nativeRange(); + return env.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text; + } + /** + * returns range for word before cursor + * + * @param {Boolean} [findAfter] - find after cursor, default: false + * @return {WrappedRange} + */ + + }, { + key: "getWordRange", + value: function getWordRange(findAfter) { + var endPoint = this.getEndPoint(); + + if (!dom.isCharPoint(endPoint)) { + return this; + } + + var startPoint = dom.prevPointUntil(endPoint, function (point) { + return !dom.isCharPoint(point); + }); + + if (findAfter) { + endPoint = dom.nextPointUntil(endPoint, function (point) { + return !dom.isCharPoint(point); + }); + } + + return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); + } + /** + * returns range for words before cursor + * + * @param {Boolean} [findAfter] - find after cursor, default: false + * @return {WrappedRange} + */ + + }, { + key: "getWordsRange", + value: function getWordsRange(findAfter) { + var endPoint = this.getEndPoint(); + + var isNotTextPoint = function isNotTextPoint(point) { + return !dom.isCharPoint(point) && !dom.isSpacePoint(point); + }; + + if (isNotTextPoint(endPoint)) { + return this; + } + + var startPoint = dom.prevPointUntil(endPoint, isNotTextPoint); + + if (findAfter) { + endPoint = dom.nextPointUntil(endPoint, isNotTextPoint); + } + + return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); + } + /** + * returns range for words before cursor that match with a Regex + * + * example: + * range: 'hi @Peter Pan' + * regex: '/@[a-z ]+/i' + * return range: '@Peter Pan' + * + * @param {RegExp} [regex] + * @return {WrappedRange|null} + */ + + }, { + key: "getWordsMatchRange", + value: function getWordsMatchRange(regex) { + var endPoint = this.getEndPoint(); + var startPoint = dom.prevPointUntil(endPoint, function (point) { + if (!dom.isCharPoint(point) && !dom.isSpacePoint(point)) { + return true; + } + + var rng = new WrappedRange(point.node, point.offset, endPoint.node, endPoint.offset); + var result = regex.exec(rng.toString()); + return result && result.index === 0; + }); + var rng = new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); + var text = rng.toString(); + var result = regex.exec(text); + + if (result && result[0].length === text.length) { + return rng; + } else { + return null; + } + } + /** + * create offsetPath bookmark + * + * @param {Node} editable + */ + + }, { + key: "bookmark", + value: function bookmark(editable) { + return { + s: { + path: dom.makeOffsetPath(editable, this.sc), + offset: this.so + }, + e: { + path: dom.makeOffsetPath(editable, this.ec), + offset: this.eo + } + }; + } + /** + * create offsetPath bookmark base on paragraph + * + * @param {Node[]} paras + */ + + }, { + key: "paraBookmark", + value: function paraBookmark(paras) { + return { + s: { + path: lists.tail(dom.makeOffsetPath(lists.head(paras), this.sc)), + offset: this.so + }, + e: { + path: lists.tail(dom.makeOffsetPath(lists.last(paras), this.ec)), + offset: this.eo + } + }; + } + /** + * getClientRects + * @return {Rect[]} + */ + + }, { + key: "getClientRects", + value: function getClientRects() { + var nativeRng = this.nativeRange(); + return nativeRng.getClientRects(); + } + }]); + + return WrappedRange; +}(); +/** + * Data structure + * * BoundaryPoint: a point of dom tree + * * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range + * + * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position + */ + + +/* harmony default export */ const range = ({ + /** + * create Range Object From arguments or Browser Selection + * + * @param {Node} sc - start container + * @param {Number} so - start offset + * @param {Node} ec - end container + * @param {Number} eo - end offset + * @return {WrappedRange} + */ + create: function create(sc, so, ec, eo) { + if (arguments.length === 4) { + return new WrappedRange(sc, so, ec, eo); + } else if (arguments.length === 2) { + // collapsed + ec = sc; + eo = so; + return new WrappedRange(sc, so, ec, eo); + } else { + var wrappedRange = this.createFromSelection(); + + if (!wrappedRange && arguments.length === 1) { + var bodyElement = arguments[0]; + + if (dom.isEditable(bodyElement)) { + bodyElement = bodyElement.lastChild; + } + + return this.createFromBodyElement(bodyElement, dom.emptyPara === arguments[0].innerHTML); + } + + return wrappedRange; + } + }, + createFromBodyElement: function createFromBodyElement(bodyElement) { + var isCollapseToStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var wrappedRange = this.createFromNode(bodyElement); + return wrappedRange.collapse(isCollapseToStart); + }, + createFromSelection: function createFromSelection() { + var sc, so, ec, eo; + + if (env.isW3CRangeSupport) { + var selection = document.getSelection(); + + if (!selection || selection.rangeCount === 0) { + return null; + } else if (dom.isBody(selection.anchorNode)) { + // Firefox: returns entire body as range on initialization. + // We won't never need it. + return null; + } + + var nativeRng = selection.getRangeAt(0); + sc = nativeRng.startContainer; + so = nativeRng.startOffset; + ec = nativeRng.endContainer; + eo = nativeRng.endOffset; + } else { + // IE8: TextRange + var textRange = document.selection.createRange(); + var textRangeEnd = textRange.duplicate(); + textRangeEnd.collapse(false); + var textRangeStart = textRange; + textRangeStart.collapse(true); + var startPoint = textRangeToPoint(textRangeStart, true); + var endPoint = textRangeToPoint(textRangeEnd, false); // same visible point case: range was collapsed. + + if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) && dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) && endPoint.node.nextSibling === startPoint.node) { + startPoint = endPoint; + } + + sc = startPoint.cont; + so = startPoint.offset; + ec = endPoint.cont; + eo = endPoint.offset; + } + + return new WrappedRange(sc, so, ec, eo); + }, + + /** + * @method + * + * create WrappedRange from node + * + * @param {Node} node + * @return {WrappedRange} + */ + createFromNode: function createFromNode(node) { + var sc = node; + var so = 0; + var ec = node; + var eo = dom.nodeLength(ec); // browsers can't target a picture or void node + + if (dom.isVoid(sc)) { + so = dom.listPrev(sc).length - 1; + sc = sc.parentNode; + } + + if (dom.isBR(ec)) { + eo = dom.listPrev(ec).length - 1; + ec = ec.parentNode; + } else if (dom.isVoid(ec)) { + eo = dom.listPrev(ec).length; + ec = ec.parentNode; + } + + return this.create(sc, so, ec, eo); + }, + + /** + * create WrappedRange from node after position + * + * @param {Node} node + * @return {WrappedRange} + */ + createFromNodeBefore: function createFromNodeBefore(node) { + return this.createFromNode(node).collapse(true); + }, + + /** + * create WrappedRange from node after position + * + * @param {Node} node + * @return {WrappedRange} + */ + createFromNodeAfter: function createFromNodeAfter(node) { + return this.createFromNode(node).collapse(); + }, + + /** + * @method + * + * create WrappedRange from bookmark + * + * @param {Node} editable + * @param {Object} bookmark + * @return {WrappedRange} + */ + createFromBookmark: function createFromBookmark(editable, bookmark) { + var sc = dom.fromOffsetPath(editable, bookmark.s.path); + var so = bookmark.s.offset; + var ec = dom.fromOffsetPath(editable, bookmark.e.path); + var eo = bookmark.e.offset; + return new WrappedRange(sc, so, ec, eo); + }, + + /** + * @method + * + * create WrappedRange from paraBookmark + * + * @param {Object} bookmark + * @param {Node[]} paras + * @return {WrappedRange} + */ + createFromParaBookmark: function createFromParaBookmark(bookmark, paras) { + var so = bookmark.s.offset; + var eo = bookmark.e.offset; + var sc = dom.fromOffsetPath(lists.head(paras), bookmark.s.path); + var ec = dom.fromOffsetPath(lists.last(paras), bookmark.e.path); + return new WrappedRange(sc, so, ec, eo); + } +}); +;// CONCATENATED MODULE: ./src/js/core/key.js + + +var KEY_MAP = { + 'BACKSPACE': 8, + 'TAB': 9, + 'ENTER': 13, + 'ESCAPE': 27, + 'SPACE': 32, + 'DELETE': 46, + // Arrow + 'LEFT': 37, + 'UP': 38, + 'RIGHT': 39, + 'DOWN': 40, + // Number: 0-9 + 'NUM0': 48, + 'NUM1': 49, + 'NUM2': 50, + 'NUM3': 51, + 'NUM4': 52, + 'NUM5': 53, + 'NUM6': 54, + 'NUM7': 55, + 'NUM8': 56, + // Alphabet: a-z + 'B': 66, + 'E': 69, + 'I': 73, + 'J': 74, + 'K': 75, + 'L': 76, + 'R': 82, + 'S': 83, + 'U': 85, + 'V': 86, + 'Y': 89, + 'Z': 90, + 'SLASH': 191, + 'LEFTBRACKET': 219, + 'BACKSLASH': 220, + 'RIGHTBRACKET': 221, + // Navigation + 'HOME': 36, + 'END': 35, + 'PAGEUP': 33, + 'PAGEDOWN': 34 +}; +/** + * @class core.key + * + * Object for keycodes. + * + * @singleton + * @alternateClassName key + */ + +/* harmony default export */ const key = ({ + /** + * @method isEdit + * + * @param {Number} keyCode + * @return {Boolean} + */ + isEdit: function isEdit(keyCode) { + return lists.contains([KEY_MAP.BACKSPACE, KEY_MAP.TAB, KEY_MAP.ENTER, KEY_MAP.SPACE, KEY_MAP.DELETE], keyCode); + }, + + /** + * @method isMove + * + * @param {Number} keyCode + * @return {Boolean} + */ + isMove: function isMove(keyCode) { + return lists.contains([KEY_MAP.LEFT, KEY_MAP.UP, KEY_MAP.RIGHT, KEY_MAP.DOWN], keyCode); + }, + + /** + * @method isNavigation + * + * @param {Number} keyCode + * @return {Boolean} + */ + isNavigation: function isNavigation(keyCode) { + return lists.contains([KEY_MAP.HOME, KEY_MAP.END, KEY_MAP.PAGEUP, KEY_MAP.PAGEDOWN], keyCode); + }, + + /** + * @property {Object} nameFromCode + * @property {String} nameFromCode.8 "BACKSPACE" + */ + nameFromCode: func.invertObject(KEY_MAP), + code: KEY_MAP +}); +;// CONCATENATED MODULE: ./src/js/core/async.js + +/** + * @method readFileAsDataURL + * + * read contents of file as representing URL + * + * @param {File} file + * @return {Promise} - then: dataUrl + */ + +function readFileAsDataURL(file) { + return external_jQuery_default().Deferred(function (deferred) { + external_jQuery_default().extend(new FileReader(), { + onload: function onload(e) { + var dataURL = e.target.result; + deferred.resolve(dataURL); + }, + onerror: function onerror(err) { + deferred.reject(err); + } + }).readAsDataURL(file); + }).promise(); +} +/** + * @method createImage + * + * create `` from url string + * + * @param {String} url + * @return {Promise} - then: $image + */ + +function createImage(url) { + return external_jQuery_default().Deferred(function (deferred) { + var $img = external_jQuery_default()(''); + $img.one('load', function () { + $img.off('error abort'); + deferred.resolve($img); + }).one('error abort', function () { + $img.off('load').detach(); + deferred.reject($img); + }).css({ + display: 'none' + }).appendTo(document.body).attr('src', url); + }).promise(); +} +;// CONCATENATED MODULE: ./src/js/editing/History.js +function History_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function History_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 History_createClass(Constructor, protoProps, staticProps) { if (protoProps) History_defineProperties(Constructor.prototype, protoProps); if (staticProps) History_defineProperties(Constructor, staticProps); return Constructor; } + + + +var History = /*#__PURE__*/function () { + function History(context) { + History_classCallCheck(this, History); + + this.stack = []; + this.stackOffset = -1; + this.context = context; + this.$editable = context.layoutInfo.editable; + this.editable = this.$editable[0]; + } + + History_createClass(History, [{ + key: "makeSnapshot", + value: function makeSnapshot() { + var rng = range.create(this.editable); + var emptyBookmark = { + s: { + path: [], + offset: 0 + }, + e: { + path: [], + offset: 0 + } + }; + return { + contents: this.$editable.html(), + bookmark: rng && rng.isOnEditable() ? rng.bookmark(this.editable) : emptyBookmark + }; + } + }, { + key: "applySnapshot", + value: function applySnapshot(snapshot) { + if (snapshot.contents !== null) { + this.$editable.html(snapshot.contents); + } + + if (snapshot.bookmark !== null) { + range.createFromBookmark(this.editable, snapshot.bookmark).select(); + } + } + /** + * @method rewind + * Rewinds the history stack back to the first snapshot taken. + * Leaves the stack intact, so that "Redo" can still be used. + */ + + }, { + key: "rewind", + value: function rewind() { + // Create snap shot if not yet recorded + if (this.$editable.html() !== this.stack[this.stackOffset].contents) { + this.recordUndo(); + } // Return to the first available snapshot. + + + this.stackOffset = 0; // Apply that snapshot. + + this.applySnapshot(this.stack[this.stackOffset]); + } + /** + * @method commit + * Resets history stack, but keeps current editor's content. + */ + + }, { + key: "commit", + value: function commit() { + // Clear the stack. + this.stack = []; // Restore stackOffset to its original value. + + this.stackOffset = -1; // Record our first snapshot (of nothing). + + this.recordUndo(); + } + /** + * @method reset + * Resets the history stack completely; reverting to an empty editor. + */ + + }, { + key: "reset", + value: function reset() { + // Clear the stack. + this.stack = []; // Restore stackOffset to its original value. + + this.stackOffset = -1; // Clear the editable area. + + this.$editable.html(''); // Record our first snapshot (of nothing). + + this.recordUndo(); + } + /** + * undo + */ + + }, { + key: "undo", + value: function undo() { + // Create snap shot if not yet recorded + if (this.$editable.html() !== this.stack[this.stackOffset].contents) { + this.recordUndo(); + } + + if (this.stackOffset > 0) { + this.stackOffset--; + this.applySnapshot(this.stack[this.stackOffset]); + } + } + /** + * redo + */ + + }, { + key: "redo", + value: function redo() { + if (this.stack.length - 1 > this.stackOffset) { + this.stackOffset++; + this.applySnapshot(this.stack[this.stackOffset]); + } + } + /** + * recorded undo + */ + + }, { + key: "recordUndo", + value: function recordUndo() { + this.stackOffset++; // Wash out stack after stackOffset + + if (this.stack.length > this.stackOffset) { + this.stack = this.stack.slice(0, this.stackOffset); + } // Create new snapshot and push it to the end + + + this.stack.push(this.makeSnapshot()); // If the stack size reachs to the limit, then slice it + + if (this.stack.length > this.context.options.historyLimit) { + this.stack.shift(); + this.stackOffset -= 1; + } + } + }]); + + return History; +}(); + + +;// CONCATENATED MODULE: ./src/js/editing/Style.js +function Style_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function Style_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 Style_createClass(Constructor, protoProps, staticProps) { if (protoProps) Style_defineProperties(Constructor.prototype, protoProps); if (staticProps) Style_defineProperties(Constructor, staticProps); return Constructor; } + + + + + + +var Style = /*#__PURE__*/function () { + function Style() { + Style_classCallCheck(this, Style); + } + + Style_createClass(Style, [{ + key: "jQueryCSS", + value: + /** + * @method jQueryCSS + * + * [workaround] for old jQuery + * passing an array of style properties to .css() + * will result in an object of property-value pairs. + * (compability with version < 1.9) + * + * @private + * @param {jQuery} $obj + * @param {Array} propertyNames - An array of one or more CSS properties. + * @return {Object} + */ + function jQueryCSS($obj, propertyNames) { + var result = {}; + external_jQuery_default().each(propertyNames, function (idx, propertyName) { + result[propertyName] = $obj.css(propertyName); + }); + return result; + } + /** + * returns style object from node + * + * @param {jQuery} $node + * @return {Object} + */ + + }, { + key: "fromNode", + value: function fromNode($node) { + var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height']; + var styleInfo = this.jQueryCSS($node, properties) || {}; + var fontSize = $node[0].style.fontSize || styleInfo['font-size']; + styleInfo['font-size'] = parseInt(fontSize, 10); + styleInfo['font-size-unit'] = fontSize.match(/[a-z%]+$/); + return styleInfo; + } + /** + * paragraph level style + * + * @param {WrappedRange} rng + * @param {Object} styleInfo + */ + + }, { + key: "stylePara", + value: function stylePara(rng, styleInfo) { + external_jQuery_default().each(rng.nodes(dom.isPara, { + includeAncestor: true + }), function (idx, para) { + external_jQuery_default()(para).css(styleInfo); + }); + } + /** + * insert and returns styleNodes on range. + * + * @param {WrappedRange} rng + * @param {Object} [options] - options for styleNodes + * @param {String} [options.nodeName] - default: `SPAN` + * @param {Boolean} [options.expandClosestSibling] - default: `false` + * @param {Boolean} [options.onlyPartialContains] - default: `false` + * @return {Node[]} + */ + + }, { + key: "styleNodes", + value: function styleNodes(rng, options) { + rng = rng.splitText(); + var nodeName = options && options.nodeName || 'SPAN'; + var expandClosestSibling = !!(options && options.expandClosestSibling); + var onlyPartialContains = !!(options && options.onlyPartialContains); + + if (rng.isCollapsed()) { + return [rng.insertNode(dom.create(nodeName))]; + } + + var pred = dom.makePredByNodeName(nodeName); + var nodes = rng.nodes(dom.isText, { + fullyContains: true + }).map(function (text) { + return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName); + }); + + if (expandClosestSibling) { + if (onlyPartialContains) { + var nodesInRange = rng.nodes(); // compose with partial contains predication + + pred = func.and(pred, function (node) { + return lists.contains(nodesInRange, node); + }); + } + + return nodes.map(function (node) { + var siblings = dom.withClosestSiblings(node, pred); + var head = lists.head(siblings); + var tails = lists.tail(siblings); + external_jQuery_default().each(tails, function (idx, elem) { + dom.appendChildNodes(head, elem.childNodes); + dom.remove(elem); + }); + return lists.head(siblings); + }); + } else { + return nodes; + } + } + /** + * get current style on cursor + * + * @param {WrappedRange} rng + * @return {Object} - object contains style properties. + */ + + }, { + key: "current", + value: function current(rng) { + var $cont = external_jQuery_default()(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc); + var styleInfo = this.fromNode($cont); // document.queryCommandState for toggle state + // [workaround] prevent Firefox nsresult: "0x80004005 (NS_ERROR_FAILURE)" + + try { + styleInfo = external_jQuery_default().extend(styleInfo, { + 'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal', + 'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal', + 'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal', + 'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal', + 'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal', + 'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal', + 'font-family': document.queryCommandValue('fontname') || styleInfo['font-family'] + }); + } catch (e) {// eslint-disable-next-line + } // list-style-type to list-style(unordered, ordered) + + + if (!rng.isOnList()) { + styleInfo['list-style'] = 'none'; + } else { + var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square']; + var isUnordered = orderedTypes.indexOf(styleInfo['list-style-type']) > -1; + styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered'; + } + + var para = dom.ancestor(rng.sc, dom.isPara); + + if (para && para.style['line-height']) { + styleInfo['line-height'] = para.style.lineHeight; + } else { + var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10); + styleInfo['line-height'] = lineHeight.toFixed(1); + } + + styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor); + styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable); + styleInfo.range = rng; + return styleInfo; + } + }]); + + return Style; +}(); + + +;// CONCATENATED MODULE: ./src/js/editing/Bullet.js +function Bullet_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function Bullet_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 Bullet_createClass(Constructor, protoProps, staticProps) { if (protoProps) Bullet_defineProperties(Constructor.prototype, protoProps); if (staticProps) Bullet_defineProperties(Constructor, staticProps); return Constructor; } + + + + + + + +var Bullet = /*#__PURE__*/function () { + function Bullet() { + Bullet_classCallCheck(this, Bullet); + } + + Bullet_createClass(Bullet, [{ + key: "insertOrderedList", + value: + /** + * toggle ordered list + */ + function insertOrderedList(editable) { + this.toggleList('OL', editable); + } + /** + * toggle unordered list + */ + + }, { + key: "insertUnorderedList", + value: function insertUnorderedList(editable) { + this.toggleList('UL', editable); + } + /** + * indent + */ + + }, { + key: "indent", + value: function indent(editable) { + var _this = this; + + var rng = range.create(editable).wrapBodyInlineWithPara(); + var paras = rng.nodes(dom.isPara, { + includeAncestor: true + }); + var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); + external_jQuery_default().each(clustereds, function (idx, paras) { + var head = lists.head(paras); + + if (dom.isLi(head)) { + var previousList = _this.findList(head.previousSibling); + + if (previousList) { + paras.map(function (para) { + return previousList.appendChild(para); + }); + } else { + _this.wrapList(paras, head.parentNode.nodeName); + + paras.map(function (para) { + return para.parentNode; + }).map(function (para) { + return _this.appendToPrevious(para); + }); + } + } else { + external_jQuery_default().each(paras, function (idx, para) { + external_jQuery_default()(para).css('marginLeft', function (idx, val) { + return (parseInt(val, 10) || 0) + 25; + }); + }); + } + }); + rng.select(); + } + /** + * outdent + */ + + }, { + key: "outdent", + value: function outdent(editable) { + var _this2 = this; + + var rng = range.create(editable).wrapBodyInlineWithPara(); + var paras = rng.nodes(dom.isPara, { + includeAncestor: true + }); + var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); + external_jQuery_default().each(clustereds, function (idx, paras) { + var head = lists.head(paras); + + if (dom.isLi(head)) { + _this2.releaseList([paras]); + } else { + external_jQuery_default().each(paras, function (idx, para) { + external_jQuery_default()(para).css('marginLeft', function (idx, val) { + val = parseInt(val, 10) || 0; + return val > 25 ? val - 25 : ''; + }); + }); + } + }); + rng.select(); + } + /** + * toggle list + * + * @param {String} listName - OL or UL + */ + + }, { + key: "toggleList", + value: function toggleList(listName, editable) { + var _this3 = this; + + var rng = range.create(editable).wrapBodyInlineWithPara(); + var paras = rng.nodes(dom.isPara, { + includeAncestor: true + }); + var bookmark = rng.paraBookmark(paras); + var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); // paragraph to list + + if (lists.find(paras, dom.isPurePara)) { + var wrappedParas = []; + external_jQuery_default().each(clustereds, function (idx, paras) { + wrappedParas = wrappedParas.concat(_this3.wrapList(paras, listName)); + }); + paras = wrappedParas; // list to paragraph or change list style + } else { + var diffLists = rng.nodes(dom.isList, { + includeAncestor: true + }).filter(function (listNode) { + return !external_jQuery_default().nodeName(listNode, listName); + }); + + if (diffLists.length) { + external_jQuery_default().each(diffLists, function (idx, listNode) { + dom.replace(listNode, listName); + }); + } else { + paras = this.releaseList(clustereds, true); + } + } + + range.createFromParaBookmark(bookmark, paras).select(); + } + /** + * @param {Node[]} paras + * @param {String} listName + * @return {Node[]} + */ + + }, { + key: "wrapList", + value: function wrapList(paras, listName) { + var head = lists.head(paras); + var last = lists.last(paras); + var prevList = dom.isList(head.previousSibling) && head.previousSibling; + var nextList = dom.isList(last.nextSibling) && last.nextSibling; + var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last); // P to LI + + paras = paras.map(function (para) { + return dom.isPurePara(para) ? dom.replace(para, 'LI') : para; + }); // append to list(