tui-editor
Version:
GFM Markdown Wysiwyg Editor - Productive and Extensible
1,755 lines (1,434 loc) • 1.35 MB
JavaScript
/*!
* tui-editor
* @version 1.4.6
* @author NHN FE Development Lab <dl_javascript@nhn.com> (https://nhn.github.io/tui.editor/)
* @license MIT
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("jquery"), require("tui-code-snippet"), require("codemirror"), require("to-mark"), require("tui-chart"), require("squire-rte"), require("markdown-it"), require("highlight.js"), require("tui-color-picker"), require("plantuml-encoder"));
else if(typeof define === 'function' && define.amd)
define(["jquery", "tui-code-snippet", "codemirror", "to-mark", "tui-chart", "squire-rte", "markdown-it", "highlight.js", "tui-color-picker", "plantuml-encoder"], factory);
else if(typeof exports === 'object')
exports["Editor"] = factory(require("jquery"), require("tui-code-snippet"), require("codemirror"), require("to-mark"), require("tui-chart"), require("squire-rte"), require("markdown-it"), require("highlight.js"), require("tui-color-picker"), require("plantuml-encoder"));
else
root["tui"] = root["tui"] || {}, root["tui"]["Editor"] = factory(root["$"], (root["tui"] && root["tui"]["util"]), root["CodeMirror"], root["toMark"], (root["tui"] && root["tui"]["chart"]), root["Squire"], root["markdownit"], root["hljs"], (root["tui"] && root["tui"]["colorPicker"]), root["plantumlEncoder"]);
})(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_10__, __WEBPACK_EXTERNAL_MODULE_42__, __WEBPACK_EXTERNAL_MODULE_57__, __WEBPACK_EXTERNAL_MODULE_79__, __WEBPACK_EXTERNAL_MODULE_85__, __WEBPACK_EXTERNAL_MODULE_94__, __WEBPACK_EXTERNAL_MODULE_205__, __WEBPACK_EXTERNAL_MODULE_207__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "dist/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 55);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
/***/ }),
/* 1 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
* @fileoverview Implements CommandManager
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
var _tuiCodeSnippet = __webpack_require__(1);
var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet);
var _command = __webpack_require__(84);
var _command2 = _interopRequireDefault(_command);
var _util = __webpack_require__(38);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var KEYMAP_OS_INDEX = _util.isMac ? 1 : 0;
/**
* Class CommandManager
*/
var CommandManager = function () {
/**
* @param {ToastUIEditor} base nedInstance
* @param {object} [options={}] - option object
* @param {boolean} [options.useCommandShortcut=true] - execute command with keyMap
*/
function CommandManager(base) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, CommandManager);
this._command = new _tuiCodeSnippet2.default.Map();
this._mdCommand = new _tuiCodeSnippet2.default.Map();
this._wwCommand = new _tuiCodeSnippet2.default.Map();
this._options = _jquery2.default.extend({
'useCommandShortcut': true
}, options);
this.base = base;
this.keyMapCommand = {};
this._initEvent();
}
/**
* You can change command before command addition by addCommandBefore event.
* @param {object} command - command
* @returns {object}
* @private
*/
_createClass(CommandManager, [{
key: '_addCommandBefore',
value: function _addCommandBefore(command) {
var commandWrapper = { command: command };
this.base.eventManager.emit('addCommandBefore', commandWrapper);
return commandWrapper.command || command;
}
/**
* Add command
* @memberof CommandManager
* @param {Command} command Command instance
* @returns {Command} Command
*/
}, {
key: 'addCommand',
value: function addCommand(command) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if (args.length) {
command = CommandManager.command.apply(CommandManager, [command].concat(args));
}
command = this._addCommandBefore(command);
var name = command.getName();
var commandBase = void 0;
if (command.isMDType()) {
commandBase = this._mdCommand;
} else if (command.isWWType()) {
commandBase = this._wwCommand;
} else if (command.isGlobalType()) {
commandBase = this._command;
}
commandBase.set(name, command);
if (command.keyMap) {
this.keyMapCommand[command.keyMap[KEYMAP_OS_INDEX]] = name;
}
return command;
}
/**
* _initEvent
* Bind event handler to eventManager
* @private
* @memberof CommandManager
*/
}, {
key: '_initEvent',
value: function _initEvent() {
var _this = this;
this.base.eventManager.listen('command', function () {
_this.exec.apply(_this, arguments);
});
this.base.eventManager.listen('keyMap', function (ev) {
if (!_this._options.useCommandShortcut) {
return;
}
var command = _this.keyMapCommand[ev.keyMap];
if (command) {
ev.data.preventDefault();
_this.exec(command);
}
});
}
/**
* Execute command
* @memberof CommandManager
* @param {String} name Command name
* @param {*} ...args Command argument
* @returns {*}
*/
}, {
key: 'exec',
value: function exec(name) {
var commandToRun = void 0,
result = void 0;
var context = this.base;
commandToRun = this._command.get(name);
if (!commandToRun) {
if (this.base.isMarkdownMode()) {
commandToRun = this._mdCommand.get(name);
context = this.base.mdEditor;
} else {
commandToRun = this._wwCommand.get(name);
context = this.base.wwEditor;
}
}
if (commandToRun) {
var _commandToRun;
for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
args.unshift(context);
result = (_commandToRun = commandToRun).exec.apply(_commandToRun, args);
}
return result;
}
}]);
return CommandManager;
}();
/**
* Create command by given editor type and property object
* @memberof CommandManager
* @param {string} type Command type
* @param {{name: string, keyMap: Array}} props Property
* @returns {*}
*/
CommandManager.command = function (type, props) {
var command = _command2.default.factory(type, props.name, props.keyMap);
_tuiCodeSnippet2.default.extend(command, props);
return command;
};
exports.default = CommandManager;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.I18n = undefined;
var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
* @fileoverview Implements i18n
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
var _tuiCodeSnippet = __webpack_require__(1);
var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var sharedInstance = void 0;
var DEFAULT_CODE = 'en_US';
/**
* Class I18n
*/
var I18n = function () {
/**
* Creates an instance of I18n.
* @memberof I18n
*/
function I18n() {
_classCallCheck(this, I18n);
this._code = DEFAULT_CODE;
this._langs = new _tuiCodeSnippet2.default.Map();
}
/**
* Set locale code
* @param {string} code locale code
*/
_createClass(I18n, [{
key: 'setCode',
value: function setCode(code) {
this._code = code;
}
/**
* Set language set
* @param {string|string[]} codes locale code
* @param {object} data language set
*/
}, {
key: 'setLanguage',
value: function setLanguage(codes, data) {
var _this = this;
codes = [].concat(codes);
codes.forEach(function (code) {
if (!_this._langs.has(code)) {
_this._langs.set(code, data);
} else {
var langData = _this._langs.get(code);
_this._langs.set(code, _tuiCodeSnippet2.default.extend(langData, data));
}
});
}
/**
* Get text of key
* @param {string} key key of text
* @param {string} code locale code
* @returns {string}
*/
}, {
key: 'get',
value: function get(key, code) {
if (!code) {
code = this._code;
}
var langSet = this._langs.get(code);
if (!langSet) {
langSet = this._langs.get(DEFAULT_CODE);
}
var text = langSet[key];
if (!text) {
throw new Error('There is no text key "' + key + '" in ' + code);
}
return text;
}
}], [{
key: 'getSharedInstance',
value: function getSharedInstance() {
if (!sharedInstance) {
sharedInstance = new I18n();
}
return sharedInstance;
}
}]);
return I18n;
}();
exports.I18n = I18n;
exports.default = new I18n();
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
var _tuiCodeSnippet = __webpack_require__(1);
var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @fileoverview DOM Utils
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
var FIND_ZWB = /\u200B/g;
/**
* isTextNode
* Check if node is text node
* @param {Node} node node to check
* @returns {boolean} result
* @ignore
*/
var isTextNode = function isTextNode(node) {
return node && node.nodeType === Node.TEXT_NODE;
};
/**
* isElemNode
* Check if node is element node
* @param {Node} node node to check
* @returns {boolean} result
* @ignore
*/
var isElemNode = function isElemNode(node) {
return node && node.nodeType === Node.ELEMENT_NODE;
};
/**
* Check that the node is block node
* @param {Node} node node
* @returns {boolean}
* @ignore
*/
var isBlockNode = function isBlockNode(node) {
return (/^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|DETAILS|DIALOG|DD|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H[\d]|HEADER|HGROUP|HR|LI|MAIN|NAV|OL|P|PRE|SECTION|UL)$/ig.test(this.getNodeName(node))
);
};
/**
* getNodeName
* Get node name of node
* @param {Node} node node
* @returns {string} node name
* @ignore
*/
var getNodeName = function getNodeName(node) {
if (isElemNode(node)) {
return node.tagName;
}
return 'TEXT';
};
/**
* getTextLength
* Get node offset length of node(for Range API)
* @param {Node} node node
* @returns {number} length
* @ignore
*/
var getTextLength = function getTextLength(node) {
var len = void 0;
if (isElemNode(node)) {
len = node.textContent.replace(FIND_ZWB, '').length;
} else if (isTextNode(node)) {
len = node.nodeValue.replace(FIND_ZWB, '').length;
}
return len;
};
/**
* getOffsetLength
* Get node offset length of node(for Range API)
* @param {Node} node node
* @returns {number} length
* @ignore
*/
var getOffsetLength = function getOffsetLength(node) {
var len = void 0;
if (isElemNode(node)) {
len = node.childNodes.length;
} else if (isTextNode(node)) {
len = node.nodeValue.replace(FIND_ZWB, '').length;
}
return len;
};
/**
* getNodeOffsetOfParent
* get node offset between parent's childnodes
* @param {Node} node node
* @returns {number} offset(index)
* @ignore
*/
var getNodeOffsetOfParent = function getNodeOffsetOfParent(node) {
var childNodesOfParent = node.parentNode.childNodes;
var i = void 0,
t = void 0,
found = void 0;
for (i = 0, t = childNodesOfParent.length; i < t; i += 1) {
if (childNodesOfParent[i] === node) {
found = i;
break;
}
}
return found;
};
/**
* getChildNodeByOffset
* get child node by offset
* @param {Node} node node
* @param {number} index offset index
* @returns {Node} foudned node
* @ignore
*/
var getChildNodeByOffset = function getChildNodeByOffset(node, index) {
var currentNode = void 0;
if (isTextNode(node)) {
currentNode = node;
} else if (node.childNodes.length && index >= 0) {
currentNode = node.childNodes[index];
}
return currentNode;
};
/**
* getNodeWithDirectionUntil
* find next node from passed node
* @param {strong} direction previous or next
* @param {Node} node node
* @param {string} untilNodeName parent node name to limit
* @returns {Node} founded node
* @ignore
*/
var getNodeWithDirectionUntil = function getNodeWithDirectionUntil(direction, node, untilNodeName) {
var directionKey = direction + 'Sibling';
var nodeName = void 0,
foundedNode = void 0;
while (node && !node[directionKey]) {
nodeName = getNodeName(node.parentNode);
if (nodeName === untilNodeName || nodeName === 'BODY') {
break;
}
node = node.parentNode;
}
if (node[directionKey]) {
foundedNode = node[directionKey];
}
return foundedNode;
};
/**
* getPrevOffsetNodeUntil
* get prev node of childnode pointed with index
* @param {Node} node node
* @param {number} index offset index
* @param {string} untilNodeName parent node name to limit
* @returns {Node} founded node
* @ignore
*/
var getPrevOffsetNodeUntil = function getPrevOffsetNodeUntil(node, index, untilNodeName) {
var prevNode = void 0;
if (index > 0) {
prevNode = getChildNodeByOffset(node, index - 1);
} else {
prevNode = getNodeWithDirectionUntil('previous', node, untilNodeName);
}
return prevNode;
};
var getParentUntilBy = function getParentUntilBy(node, matchCondition, stopCondition) {
var foundedNode = void 0;
while (node.parentNode && !matchCondition(node.parentNode)) {
node = node.parentNode;
if (stopCondition && stopCondition(node.parentNode)) {
break;
}
}
if (matchCondition(node.parentNode)) {
foundedNode = node;
}
return foundedNode;
};
/**
* getParentUntil
* get parent node until paseed node name
* @param {Node} node node
* @param {string|HTMLNode} untilNode node name or node to limit
* @returns {Node} founded node
* @ignore
*/
var getParentUntil = function getParentUntil(node, untilNode) {
var foundedNode = void 0;
if (_tuiCodeSnippet2.default.isString(untilNode)) {
foundedNode = getParentUntilBy(node, function (targetNode) {
return untilNode === getNodeName(targetNode);
});
} else {
foundedNode = getParentUntilBy(node, function (targetNode) {
return untilNode === targetNode;
});
}
return foundedNode;
};
/**
* getNodeWithDirectionUnderParent
* get node on the given direction under given parent
* @param {strong} direction previous or next
* @param {Node} node node
* @param {string|Node} underNode parent node name to limit
* @returns {Node} founded node
* @ignore
*/
var getNodeWithDirectionUnderParent = function getNodeWithDirectionUnderParent(direction, node, underNode) {
var directionKey = direction + 'Sibling';
var foundedNode = void 0;
node = getParentUntil(node, underNode);
if (node && node[directionKey]) {
foundedNode = node[directionKey];
}
return foundedNode;
};
/**
* getTopPrevNodeUnder
* get top previous top level node under given node
* @param {Node} node node
* @param {Node} underNode underNode
* @returns {Node} founded node
* @ignore
*/
var getTopPrevNodeUnder = function getTopPrevNodeUnder(node, underNode) {
return getNodeWithDirectionUnderParent('previous', node, underNode);
};
/**
* getNextTopBlockNode
* get next top level block node
* @param {Node} node node
* @param {Node} underNode underNode
* @returns {Node} founded node
* @ignore
*/
var getTopNextNodeUnder = function getTopNextNodeUnder(node, underNode) {
return getNodeWithDirectionUnderParent('next', node, underNode);
};
/**
* Get parent element the body element
* @param {Node} node Node for start searching
* @returns {Node}
* @ignore
*/
var getTopBlockNode = function getTopBlockNode(node) {
return getParentUntil(node, 'BODY');
};
/**
* Get previous text node
* @param {Node} node Node for start searching
* @returns {Node}
* @ignore
*/
var getPrevTextNode = function getPrevTextNode(node) {
node = node.previousSibling || node.parentNode;
while (!isTextNode(node) && getNodeName(node) !== 'BODY') {
if (node.previousSibling) {
node = node.previousSibling;
while (node.lastChild) {
node = node.lastChild;
}
} else {
node = node.parentNode;
}
}
if (getNodeName(node) === 'BODY') {
node = null;
}
return node;
};
/**
* test whether root contains the given node
* @param {HTMLNode} root - root node
* @param {HTMLNode} node - node to test
* @returns {Boolean} true if root contains node
*/
var containsNode = function containsNode(root, node) {
var walker = document.createTreeWalker(root, 4, null, false);
var found = root === node;
while (!found && walker.nextNode()) {
found = walker.currentNode === node;
}
return found;
};
/**
* find node by offset
* @param {HTMLElement} root Root element
* @param {Array.<number>} offsetList offset list
* @param {function} textNodeFilter Text node filter
* @returns {Array}
* @ignore
*/
var findOffsetNode = function findOffsetNode(root, offsetList, textNodeFilter) {
var result = [];
var text = '';
var walkerOffset = 0;
var newWalkerOffset = void 0;
if (!offsetList.length) {
return result;
}
var offset = offsetList.shift();
var walker = document.createTreeWalker(root, 4, null, false);
while (walker.nextNode()) {
text = walker.currentNode.nodeValue || '';
if (textNodeFilter) {
text = textNodeFilter(text);
}
newWalkerOffset = walkerOffset + text.length;
while (newWalkerOffset >= offset) {
result.push({
container: walker.currentNode,
offsetInContainer: offset - walkerOffset,
offset: offset
});
if (!offsetList.length) {
return result;
}
offset = offsetList.shift();
}
walkerOffset = newWalkerOffset;
}
// there should be offset left
do {
result.push({
container: walker.currentNode,
offsetInContainer: text.length,
offset: offset
});
offset = offsetList.shift();
} while (!_tuiCodeSnippet2.default.isUndefined(offset));
return result;
};
var getNodeInfo = function getNodeInfo(node) {
var path = {};
path.tagName = node.nodeName;
if (node.id) {
path.id = node.id;
}
var className = node.className.trim();
if (className) {
path.className = className;
}
return path;
};
var getPath = function getPath(node, root) {
var paths = [];
while (node && node !== root) {
if (isElemNode(node)) {
paths.unshift(getNodeInfo(node));
}
node = node.parentNode;
}
return paths;
};
/**
* Find next, previous TD or TH element by given TE element
* @param {HTMLElement} node TD element
* @param {string} direction 'next' or 'previous'
* @returns {HTMLElement|null}
* @ignore
*/
var getTableCellByDirection = function getTableCellByDirection(node, direction) {
var targetElement = null;
if (!_tuiCodeSnippet2.default.isUndefined(direction) && (direction === 'next' || direction === 'previous')) {
if (direction === 'next') {
targetElement = node.nextElementSibling;
} else {
targetElement = node.previousElementSibling;
}
}
return targetElement;
};
/**
* Find sibling TR's TD element by given TD and direction
* @param {HTMLElement} node TD element
* @param {string} direction Boolean value for find first TD in next line
* @param {boolean} [needEdgeCell=false] Boolean value for find first TD in next line
* @returns {HTMLElement|null}
* @ignore
*/
var getSiblingRowCellByDirection = function getSiblingRowCellByDirection(node, direction, needEdgeCell) {
var tableCellElement = null;
var $node = void 0,
index = void 0,
$targetRowElement = void 0,
$currentContainer = void 0,
$siblingContainer = void 0,
isSiblingContainerExists = void 0;
if (!_tuiCodeSnippet2.default.isUndefined(direction) && (direction === 'next' || direction === 'previous')) {
if (node) {
$node = (0, _jquery2.default)(node);
if (direction === 'next') {
$targetRowElement = $node.parent().next();
$currentContainer = $node.parents('thead');
$siblingContainer = $currentContainer[0] && $currentContainer.next();
isSiblingContainerExists = $siblingContainer && getNodeName($siblingContainer[0]) === 'TBODY';
index = 0;
} else {
$targetRowElement = $node.parent().prev();
$currentContainer = $node.parents('tbody');
$siblingContainer = $currentContainer[0] && $currentContainer.prev();
isSiblingContainerExists = $siblingContainer && getNodeName($siblingContainer[0]) === 'THEAD';
index = node.parentNode.childNodes.length - 1;
}
if (_tuiCodeSnippet2.default.isUndefined(needEdgeCell) || !needEdgeCell) {
index = getNodeOffsetOfParent(node);
}
if ($targetRowElement[0]) {
tableCellElement = $targetRowElement.children('td,th')[index];
} else if ($currentContainer[0] && isSiblingContainerExists) {
tableCellElement = $siblingContainer.find('td,th')[index];
}
}
}
return tableCellElement;
};
/**
* Check that the inline node is supported by markdown
* @param {Node} node TD element
* @returns {boolean}
* @ignore
*/
var isMDSupportInlineNode = function isMDSupportInlineNode(node) {
return (/^(A|B|BR|CODE|DEL|EM|I|IMG|S|SPAN|STRONG)$/ig.test(node.nodeName)
);
};
/**
* Check that node is styled node.
* Styled node is a node that has text and decorates text.
* @param {Node} node TD element
* @returns {boolean}
* @ignore
*/
var isStyledNode = function isStyledNode(node) {
return (/^(A|ABBR|ACRONYM|B|BDI|BDO|BIG|CITE|CODE|DEL|DFN|EM|I|INS|KBD|MARK|Q|S|SAMP|SMALL|SPAN|STRONG|SUB|SUP|U|VAR)$/ig.test(node.nodeName)
);
};
/**
* remove node from 'start' node to 'end-1' node inside parent
* if 'end' node is null, remove all child nodes after 'start' node.
* @param {Node} parent - parent node
* @param {Node} start - start node to remove
* @param {Node} end - end node to remove
* @ignore
*/
var removeChildFromStartToEndNode = function removeChildFromStartToEndNode(parent, start, end) {
var child = start;
if (!child || parent !== child.parentNode) {
return;
}
while (child !== end) {
var next = child.nextSibling;
parent.removeChild(child);
child = next;
}
};
/**
* remove nodes along the direction from the node to reach targetParent node
* @param {Node} targetParent - stop removing when reach target parent node
* @param {Node} node - start node
* @param {boolean} isForward - direction
* @ignore
*/
var removeNodesByDirection = function removeNodesByDirection(targetParent, node, isForward) {
var parent = node;
while (parent !== targetParent) {
var nextParent = parent.parentNode;
var _parent = parent,
nextSibling = _parent.nextSibling,
previousSibling = _parent.previousSibling;
if (!isForward && nextSibling) {
removeChildFromStartToEndNode(nextParent, nextSibling, null);
} else if (isForward && previousSibling) {
removeChildFromStartToEndNode(nextParent, nextParent.childNodes[0], parent);
}
parent = nextParent;
}
};
var getLeafNode = function getLeafNode(node) {
var result = node;
while (result.childNodes && result.childNodes.length) {
var _result = result,
nextLeaf = _result.firstChild;
// When inline tag have empty text node with other childnodes, ignore empty text node.
if (isTextNode(nextLeaf) && !getTextLength(nextLeaf)) {
result = nextLeaf.nextSibling || nextLeaf;
} else {
result = nextLeaf;
}
}
return result;
};
/**
* check if a coordinates is inside a task box
* @param {object} style - computed style of task box
* @param {number} offsetX - event x offset
* @param {number} offsetY - event y offset
* @returns {boolean}
* @ignore
*/
var isInsideTaskBox = function isInsideTaskBox(style, offsetX, offsetY) {
var rect = {
left: parseInt(style.left, 10),
top: parseInt(style.top, 10),
width: parseInt(style.width, 10),
height: parseInt(style.height, 10)
};
return offsetX >= rect.left && offsetX <= rect.left + rect.width && offsetY >= rect.top && offsetY <= rect.top + rect.height;
};
/**
* Check whether node is OL or UL
* @param {node} node - node
* @returns {boolean} - whether node is OL or UL
* @ignore
*/
var isListNode = function isListNode(node) {
if (!node) {
return false;
}
return node.nodeName === 'UL' || node.nodeName === 'OL';
};
/**
* Check whether node is first list item
* @param {node} node - node
* @returns {boolean} whether node is first list item
* @ignore
*/
var isFirstListItem = function isFirstListItem(node) {
var nodeName = node.nodeName,
parentNode = node.parentNode;
return nodeName === 'LI' && node === parentNode.firstChild;
};
/**
* Check whether node is first level list item
* @param {node} node - node
* @returns {boolean} whether node is first level list item
* @ignore
*/
var isFirstLevelListItem = function isFirstLevelListItem(node) {
var nodeName = node.nodeName,
listNode = node.parentNode;
var listParentNode = listNode.parentNode;
return nodeName === 'LI' && !isListNode(listParentNode);
};
/**
* Merge node to target node and detach node
* @param {node} node - node
* @param {node} targetNode - target node
* @ignore
*/
var mergeNode = function mergeNode(node, targetNode) {
if (node.hasChildNodes()) {
_tuiCodeSnippet2.default.forEachArray(node.childNodes, function () {
targetNode.appendChild(node.firstChild);
});
targetNode.normalize();
}
if (node.parentNode) {
node.parentNode.removeChild(node);
}
};
/**
* Create hr that is not contenteditable
* @returns {node} hr is wraped div
* @ignore
*/
var createHorizontalRule = function createHorizontalRule() {
var div = document.createElement('div');
var hr = document.createElement('hr');
div.setAttribute('contenteditable', false);
hr.setAttribute('contenteditable', false);
div.appendChild(hr);
return div;
};
/**
* Create Empty Line
* @returns {node} <div><br></div>
* @private
*/
var createEmptyLine = function createEmptyLine() {
var div = document.createElement('div');
div.appendChild(document.createElement('br'));
return div;
};
/**
* Find same tagName child node and change wrapping order.
* For example, if below node need to optimize 'B' tag.
* <i><s><b>test</b></s></i>
* should be changed tag's order.
* <b><i><s>test</s></i></b>
* @param {node} node
* @param {string} tagName
* @returns {node}
* @private
*/
var changeTagOrder = function changeTagOrder(node, tagName) {
if (node.nodeName !== 'SPAN') {
var parentNode = node.parentNode;
var tempNode = node;
while (tempNode.childNodes && tempNode.childNodes.length === 1 && !isTextNode(tempNode.firstChild)) {
tempNode = tempNode.firstChild;
if (tempNode.nodeName === 'SPAN') {
break;
}
if (tempNode.nodeName === tagName) {
var wrapper = document.createElement(tagName);
mergeNode(tempNode, tempNode.parentNode);
parentNode.replaceChild(wrapper, node);
wrapper.appendChild(node);
return wrapper;
}
}
}
return node;
};
/**
* Find same tagName nodes and merge from startNode to endNode.
* @param {node} startNode
* @param {node} endNode
* @param {string} tagName
* @returns {node}
* @private
*/
var mergeSameNodes = function mergeSameNodes(startNode, endNode, tagName) {
var startBlockNode = changeTagOrder(startNode, tagName);
if (startBlockNode.nodeName === tagName) {
var endBlockNode = changeTagOrder(endNode, tagName);
var mergeTargetNode = startBlockNode;
var nextNode = startBlockNode.nextSibling;
while (nextNode) {
var tempNext = nextNode.nextSibling;
nextNode = changeTagOrder(nextNode, tagName);
if (nextNode.nodeName === tagName) {
// eslint-disable-next-line max-depth
if (mergeTargetNode) {
mergeNode(nextNode, mergeTargetNode);
} else {
mergeTargetNode = nextNode;
}
} else {
mergeTargetNode = null;
}
if (nextNode === endBlockNode) {
break;
}
nextNode = tempNext;
}
}
};
/**
* Find same tagName nodes in range and merge nodes.
* For example range is like this
* <s><b>AAA</b></s><b>BBB</b>
* nodes is changed below
* <b><s>AAA</s>BBB</b>
* @param {range} range
* @param {string} tagName
* @private
*/
var optimizeRange = function optimizeRange(range, tagName) {
var collapsed = range.collapsed,
commonAncestorContainer = range.commonAncestorContainer,
startContainer = range.startContainer,
endContainer = range.endContainer;
if (!collapsed) {
var optimizedNode = null;
if (startContainer !== endContainer) {
mergeSameNodes(getParentUntil(startContainer, commonAncestorContainer), getParentUntil(endContainer, commonAncestorContainer), tagName);
optimizedNode = commonAncestorContainer;
} else if (isTextNode(startContainer)) {
optimizedNode = startContainer.parentNode;
}
if (optimizedNode && optimizedNode.nodeName === tagName) {
var _optimizedNode = optimizedNode,
previousSibling = _optimizedNode.previousSibling;
var tempNode = void 0;
if (previousSibling) {
tempNode = changeTagOrder(previousSibling);
if (tempNode.nodeName === tagName) {
mergeNode(optimizedNode, tempNode);
}
}
var _optimizedNode2 = optimizedNode,
nextSibling = _optimizedNode2.nextSibling;
if (nextSibling) {
tempNode = changeTagOrder(nextSibling);
if (tempNode.nodeName === tagName) {
mergeNode(tempNode, optimizedNode);
}
}
}
}
};
/**
* Gets all text node from root element.
* @param {HTMLElement} root Root element
* @returns {Array} list of text nodes
*/
var getAllTextNode = function getAllTextNode(root) {
var walker = document.createTreeWalker(root, 4, null, false);
var result = [];
while (walker.nextNode()) {
var node = walker.currentNode;
if (isTextNode(node)) {
result.push(node);
}
}
return result;
};
exports.default = {
getNodeName: getNodeName,
isTextNode: isTextNode,
isElemNode: isElemNode,
isBlockNode: isBlockNode,
getTextLength: getTextLength,
getOffsetLength: getOffsetLength,
getPrevOffsetNodeUntil: getPrevOffsetNodeUntil,
getNodeOffsetOfParent: getNodeOffsetOfParent,
getChildNodeByOffset: getChildNodeByOffset,
getNodeWithDirectionUntil: getNodeWithDirectionUntil,
containsNode: containsNode,
getTopPrevNodeUnder: getTopPrevNodeUnder,
getTopNextNodeUnder: getTopNextNodeUnder,
getParentUntilBy: getParentUntilBy,
getParentUntil: getParentUntil,
getTopBlockNode: getTopBlockNode,
getPrevTextNode: getPrevTextNode,
findOffsetNode: findOffsetNode,
getPath: getPath,
getNodeInfo: getNodeInfo,
getTableCellByDirection: getTableCellByDirection,
getSiblingRowCellByDirection: getSiblingRowCellByDirection,
isMDSupportInlineNode: isMDSupportInlineNode,
isStyledNode: isStyledNode,
removeChildFromStartToEndNode: removeChildFromStartToEndNode,
removeNodesByDirection: removeNodesByDirection,
getLeafNode: getLeafNode,
isInsideTaskBox: isInsideTaskBox,
isListNode: isListNode,
isFirstListItem: isFirstListItem,
isFirstLevelListItem: isFirstLevelListItem,
mergeNode: mergeNode,
createHorizontalRule: createHorizontalRule,
createEmptyLine: createEmptyLine,
changeTagOrder: changeTagOrder,
mergeSameNodes: mergeSameNodes,
optimizeRange: optimizeRange,
getAllTextNode: getAllTextNode
};
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* @fileoverview Editor/Viewer proxy for extensions
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
/* eslint global-require: 0 no-empty: 0 */
var Editor = void 0;
try {
Editor = __webpack_require__(29);
} catch (e) {}
if (!Editor) {
try {
Editor = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"../viewer\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
} catch (e) {}
}
exports.default = Editor;
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createTableData = createTableData;
exports.createCellIndexData = createCellIndexData;
var _jquery = __webpack_require__(0);
var _jquery2 = _interopRequireDefault(_jquery);
var _tuiCodeSnippet = __webpack_require__(1);
var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Parse cell like td or th.
* @param {HTMLElement} cell - cell element like td or th
* @param {number} rowIndex - row index
* @param {number} colIndex - column index
* @returns {{
* nodeName: string,
* colspan: number,
* rowspan: number,
* content: string,
* align: ?string
* }}
* @private
*/
/**
* @fileoverview Implements tableDataHandler
* @author NHN FE Development Lab <dl_javascript@nhn.com>
*/
function _parseCell(cell, rowIndex, colIndex) {
var $cell = (0, _jquery2.default)(cell);
var colspan = $cell.attr('colspan');
var rowspan = $cell.attr('rowspan');
var nodeName = cell.nodeName;
if (nodeName !== 'TH' && nodeName !== 'TD') {
return null;
}
var cellData = {
nodeName: cell.nodeName,
colspan: colspan ? parseInt(colspan, 10) : 1,
rowspan: rowspan ? parseInt(rowspan, 10) : 1,
content: $cell.html(),
elementIndex: {
rowIndex: rowIndex,
colIndex: colIndex
}
};
if (cell.nodeName === 'TH' && cell.align) {
cellData.align = cell.align;
}
return cellData;
}
/**
* Add merged cell.
* @param {object} base - base table data
* @param {object} cellData - cell data
* @param {number} startRowIndex - start row index
* @param {number} startCellIndex - start cell index
* @private
*/
function _addMergedCell(base, cellData, startRowIndex, startCellIndex) {
var colspan = cellData.colspan,
rowspan = cellData.rowspan,
nodeName = cellData.nodeName;
var colMerged = colspan > 1;
var rowMerged = rowspan > 1;
if (!colMerged && !rowMerged) {
return;
}
var limitRowIndex = startRowIndex + rowspan;
var limitCellIndex = startCellIndex + colspan;
_tuiCodeSnippet2.default.range(startRowIndex, limitRowIndex).forEach(function (rowIndex) {
base[rowIndex] = base[rowIndex] || [];
_tuiCodeSnippet2.default.range(startCellIndex, limitCellIndex).forEach(function (cellIndex) {
var mergedData = {
nodeName: nodeName
};
if (rowIndex === startRowIndex && cellIndex === startCellIndex) {
return;
}
if (colMerged) {
mergedData.colMergeWith = startCellIndex;
}
if (rowMerged) {
mergedData.rowMergeWith = startRowIndex;
}
base[rowIndex][cellIndex] = mergedData;
});
});
}
/**
* Create table data from jQuery table Element.
* @param {jQuery} $table - jQuery table element
* @returns {Array.<Array.<object>>}
* @ignore
*/
function createTableData($table) {
var tableData = [];
$table.find('tr').each(function (rowIndex, tr) {
var stackedColCount = 0;
tableData[rowIndex] = tableData[rowIndex] || [];
(0, _jquery2.default)(tr).children().each(function (colIndex, cell) {
var cellData = _parseCell(cell, rowIndex, colIndex);
if (!cellData) {
return;
}
var dataColIndex = colIndex + stackedColCount;
while (tableData[rowIndex][dataColIndex]) {
dataColIndex += 1;
stackedColCount += 1;
}
tableData[rowIndex][dataColIndex] = cellData;
_addMergedCell(tableData, cellData, rowIndex, dataColIndex);
});
});
if ($table[0].className) {
tableData.className = $table[0].className;
}
return tableData;
}
/**
* Create cell index data of table data.
* @param {Array.<Array.<object>>} tableData - table data
* @returns {Array.<Array.<object>>}
* @ignore
*/
function createCellIndexData(tableData) {
var mappingData = [];
tableData.forEach(function (row, rowIndex) {
var mappingRow = [];
row.forEach(function (cell, colIndex) {
if (_tuiCodeSnippet2.default.isUndefined(cell.colMergeWith) && _tuiCodeSnippet2.default.isUndefined(cell.rowMergeWith)) {
mappingRow.push({
rowIndex: rowIndex,
colIndex: colIndex
});
}
});
mappingData.push(mappingRow);
});
return mappingData;
}
/**
* Get header aligns.
* @param {Array.<Array.<object>>} tableData - table data
* @returns {Array.<?string>}
* @private
*/
function _getHeaderAligns(tableData) {
var headRowData = tableData[0];
return headRowData.map(function (cellData) {
var align = void 0;
if (_tuiCodeSnippet2.default.isExisty(cellData.colMergeWith)) {
align = headRowData[cellData.colMergeWith].align;
} else {
align = cellData.align;
}
return align;
});
}
/**
* Create render data.
* @param {Array.<object>} tableData - table data
* @param {Array.<object>} cellIndexData - cell index data
* @returns {Array.<Array.<object>>}
* @ignore
*/
function createRenderData(tableData, cellIndexData) {
var headerAligns = _getHeaderAligns(tableData);
var renderData = cellIndexData.map(function (row) {
return row.map(function (_ref) {
var rowIndex = _ref.rowIndex,
colIndex = _ref.colIndex;
return _tuiCodeSnippet2.default.extend({
align: headerAligns[colIndex]
}, tableData[rowIndex][colIndex]);
});
});
if (tableData.className) {
renderData.className = tableData.className;
}
return renderData;
}
var BASIC_CELL_CONTENT = _tuiCodeSnippet2.default.browser.msie ? '' : '<br>';
/**
* Create basic cell data.
* @param {number} rowIndex - row index
* @param {number} colIndex - column index
* @param {string} nodeName - node name
* @returns {{
* nodeName: string,
* colspan: number,
* rowspan: number,
* content: string
* }}
* @ignore
*/
function createBasicCell(rowIndex, colIndex, nodeName) {
return {
nodeName: nodeName || 'TD',
colspan: 1,
rowspan: 1,
content: BASIC_CELL_CONTENT,
elementIndex: {
rowIndex: rowIndex,
colIndex: colIndex
}
};
}
/**
* Find element row index.
* @param {jQuery} $cell - cell jQuery element like td or th
* @returns {number}
* @ignore
*/
function findElementRowIndex($cell) {
var $tr = $cell.closest('tr');
var rowIndex = $tr.prevAll().length;
if ($tr.parent()[0].nodeName === 'TBODY') {
rowIndex += 1;
}
return rowIndex;
}
/**
* Find element col index.
* @param {jQuery} $cell - cell jQuery element like td or th
* @returns {number}
* @ignore
*/
function findElementColIndex($cell) {
return $cell.closest('td, th').prevAll().length;
}
/**
* Find indexes of base table data from mappin data.
* @param {Array.<Array.<object>>} cellIndexData - cell index data
* @param {jQuery} $cell - cell jQuery element like td or th
* @returns {{rowIndex: number, cellIndex: number}}
* @ignore
*/
function findCellIndex(cellIndexData, $cell) {
var elementRowIndex = findElementRowIndex($cell);
var elementColIndex = findElementColIndex($cell);
return cellIndexData[elementRowIndex][elementColIndex];
}
/**
* Find last index of col merged cells.
* @param {Array.<Array.<object>>} tableData - tableData data
* @param {number} rowIndex - row index of base data
* @param {number} colIndex - column index of tabld data
* @returns {number}
* @ignore
*/
function findRowMergedLastIndex(tableData, rowIndex, colIndex) {
var cellData = tableData[rowIndex][colIndex];
var foundRowIndex = rowIndex;
if (cellData.rowspan > 1) {
foundRowIndex += cellData.rowspan - 1;
}
return foundRowIndex;
}
/**
* Find last index of col merged cells.
* @param {Array.<Array.<object>>} tableData - tableData data
* @param {number} rowIndex - row index of base data
* @param {number} colIndex - column index of tabld data
* @returns {number}
* @ignore
*/
function findColMergedLastIndex(tableData, rowIndex, colIndex) {
var cellData = tableData[rowIndex][colIndex];
var foundColIndex = colIndex;
if (cellData.colspan > 1) {
foundColIndex += cellData.colspan - 1;
}
return foundColIndex;
}
/**
* Find cell element index.
* @param {Array.<Array.<object>>} tableData - tableData data
* @param {number} rowIndex - row index of base data
* @param {number} colIndex - col index of base data
* @returns {{rowIndex: number, colIndex: number}}
* @ignore
*/
function findElementIndex(tableData, rowIndex, colIndex) {
var cellData = tableData[rowIndex][colIndex];
rowIndex = _tuiCodeSnippet2.default.isExisty(cellData.rowMergeWith) ? cellData.rowMergeWith : rowIndex;
colIndex = _tuiCodeSnippet2.default.isExisty(cellData.colMergeWith) ? cellData.colMergeWith : colIndex;
return tableData[rowIndex][colIndex].elementIndex;
}
/**
* Stuff cells into incomplete row.
* @param {Array.<Array.<object>>} tableData - table data
* @param {number} limitIndex - limit index
* @ignore
*/
function stuffCellsIntoIncompleteRow(tableData, limitIndex) {
tableData.forEach(function (rowData, rowIndex) {
var startIndex = rowData.length;
if (startIndex) {
var nodeName = rowData[0].nodeName;
_tuiCodeSnippet2.default.range(startIndex, limitIndex).forEach(function (colIndex) {
rowData.push(createBasicCell(rowIndex, colIndex, nodeName));
});
}
});
}
/**
* Ad