![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /var/www/html/libs/absol-full/dist/js/ |
Upload File : |
/*** module: node_modules/absol-form/js/kfeditor/KFEngine.js ***/ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _AElement = _interopRequireDefault(require("absol/src/HTML5/AElement")); var _FCore = require("../core/FCore"); var _CSSParser = require("absol/src/JSX/CSSParser"); var _Array = require("absol/src/DataStructure/Array"); var _utils = require("../fdeditor/utils"); var _stringUtils = require("absol/src/String/stringUtils"); var childIndexOf = child => { return Array.prototype.indexOf.call(child.parentElement.childNodes, child); }; /** * * @param {KFEditor} editor * @constructor */ function KFEngine(editor) { this.editor = editor; /** * * @type {Selection} */ this.sel = undefined; /** * * @type {null|Array<Range>} */ this.ranges = null; /** * * @type {{ rules: KFRule[]}} */ this.definitions = { rules: [] }; this.staticRules.forEach(rule => this.define(rule)); console.log(this); } /************* RANGE ***********/ KFEngine.prototype.getSelection = function () { if (!this.sel) this.sel = document.getSelection(); return this.sel; }; KFEngine.prototype.isSelectionCollapsed = function () { this.updateRanges(); return this.ranges.length === 1 && this.ranges[0].collapsed; }; /** * * @param {Range} range * @returns {Range} */ KFEngine.prototype.computeNormalizeRange = function (range) { console.log('normal'); var startCtn = range.startContainer; var endCtn = range.endContainer; var startHardBlock = this.hardBlockOf(startCtn); var endHardBlock = this.hardBlockOf(endCtn); var startOffset = range.startOffset; var endOffset = range.endOffset; if (startHardBlock === endHardBlock) return range; var lcaNode = this.lcaOf(startCtn, endCtn); var sInE, eInS; if (this.isCavity(lcaNode) || this.isInterior(lcaNode)) { do { lcaNode = lcaNode.parentElement; } while (!this.isExterior(lcaNode)); startOffset = childIndexOf(lcaNode); endOffset = startOffset + 1; range = document.createRange(); range.setStart(lcaNode.parentElement, startOffset); range.setEnd(lcaNode.parentElement, endOffset); } else { eInS = _AElement.default.prototype.isDescendantOf.call(endHardBlock, startHardBlock); sInE = _AElement.default.prototype.isDescendantOf.call(startHardBlock, endHardBlock); if (eInS || !eInS && !sInE) { while (this.isInnerBlock(endHardBlock) || this.isCavity(endHardBlock)) { endHardBlock = endHardBlock.parentElement; } endOffset = childIndexOf(endHardBlock) + 1; endCtn = endHardBlock.parentElement; } if (sInE || !eInS && !sInE) { while (this.isInnerBlock(startHardBlock) || this.isCavity(startHardBlock)) { startHardBlock = startHardBlock.parentElement; } startOffset = childIndexOf(startHardBlock); startCtn = startHardBlock.parentElement; } range = document.createRange(); range.setStart(startCtn, startOffset); range.setEnd(endCtn, endOffset); } return range; }; /** * * @param {Range} range * @returns {boolean} */ KFEngine.prototype.isValidRange = function (range) { var ctn = range.startContainer; return _AElement.default.prototype.isDescendantOf.call(ctn, this.editor.$content); }; /** * update ranges from DOM if ranges are in content */ KFEngine.prototype.updateRanges = function () { var sel = this.getSelection(); var ranges = []; var range; for (var i = 0; i < sel.rangeCount; ++i) { range = sel.getRangeAt(i); if (this.isValidRange(range)) ranges.push(range); } if (ranges.length > 0) this.ranges = ranges; return this.ranges; }; /** * * @returns {Array<Range>|null} */ KFEngine.prototype.getRanges = function () { if (!this.ranges) this.updateRanges(); return this.ranges; }; /** * * @param {Array<Range>|Range} ranges - ranges must be in content */ KFEngine.prototype.setRanges = function (ranges) { ranges = ranges || []; if (!Array.isArray(ranges)) ranges = [ranges]; this.ranges = ranges; this.getSelection(); this.sel.removeAllRanges(); for (var i = 0; i < ranges.length; ++i) this.sel.addRange(ranges[i]); }; /** * recover range from last focus range */ KFEngine.prototype.focusRanges = function () { if (this.ranges) this.setRanges(this.ranges); }; /************* DEFINITIONS ***********/ /** * @typedef KFRule * @property {string|null} selector * @property {"void"|"interior"|"exterior"|"container"|"cavity"|"text"} [type] * @property {number[]} [specificity] * @property {string[]} [allowChildren] * @property {boolean} [hard] * @property {string[]} [formatKeys] * @property {*} [empty] * */ /** * * @type {KFRule[]} */ KFEngine.prototype.staticRules = [{ selector: '.kf-grid', type: 'exterior', allowChildren: ['.kf-grid-item'] }, { selector: '.kf-grid-item', type: "interior" }, { selector: 'tr', type: "cavity" }, { selector: 'thead', type: "cavity", allowChildren: ['tr'] }, { selector: 'tbody', type: "cavity", allowChildren: ['tr'] }, { selector: 'td', type: "interior" }, { selector: 'th', type: "interior" }, { selector: 'img', type: 'void' }, { selector: 'input', type: 'void' }, { selector: 'textarea', type: 'void' }, { selector: 'br', type: 'void' }, { selector: "table", type: "exterior", allowChildren: ['thead', 'tbody'] }, { selector: 'label', type: 'container', hard: true, empty: { text: _utils.CHAR_ZWS } }, { type: 'container', selector: '*' }]; /** * * @type {KFRule} */ KFEngine.prototype.textRule = { type: 'text', selector: null }; /** * * @param {KFRule} rule */ KFEngine.prototype.define = function (rule) { var rules = this.definitions.rules; rule.specificity = rule.specificity || (0, _CSSParser.getQuerySelectorSpecificity)(rule.selector); rule.type = rule.type || 'container'; var i = rules.length; while (i > 0) { if ((0, _Array.arrayLexicographicalCompare)(rule.specificity, rules[i - 1].specificity) > 0) { --i; } else { break; } } rules.splice(i, 0, rule); }; /** * * @param {Text|HTMLElement}nd * @returns {KFRule} */ KFEngine.prototype.ruleOfNode = function (nd) { if (this.isTextNode(nd)) return this.textRule; var rules = this.definitions.rules; var rule; for (var i = 0; i < rules.length; ++i) { rule = rules[i]; if (nd.matches(rule.selector)) return rule; } return this.staticRules[this.staticRules.length - 1]; //never }; KFEngine.prototype.isTextNode = function (nd) { return nd.nodeType === Node.TEXT_NODE; }; KFEngine.prototype.isParagraph = function (nd) { if (this.isTextNode(nd)) return false; var displayStyle = getComputedStyle(nd).getPropertyValue('display') || ''; return displayStyle === 'block'; }; KFEngine.prototype.isHardBlock = function (nd) { if (this.isTextNode(nd)) return false; if (nd.getAttribute('contenteditable')) return true; var res = false; var rule = this.ruleOfNode(nd); res = res || rule.hard || ['exterior', 'cavity', 'exterior', 'interior'].indexOf(rule.type) > 0; //other rules return res; }; //inner block contain data of module/widget KFEngine.prototype.isInnerBlock = function (nd) { return this.isCavity(nd) || this.isInterior(nd); }; KFEngine.prototype.isCavity = function (nd) { var rule = this.ruleOfNode(nd); return rule.type === "cavity"; }; KFEngine.prototype.isInterior = function (nd) { var rule = this.ruleOfNode(nd); return rule.type === "interior"; }; KFEngine.prototype.isExterior = function (nd) { var rule = this.ruleOfNode(nd); return rule.type === "exterior"; }; KFEngine.prototype.isVoid = function (nd) { var rule = this.ruleOfNode(nd); return rule.type === "void"; }; KFEngine.prototype.paragraphOf = function (nd) { if (!nd) return null; if (this.isHardBlock(nd)) return null; if (this.isParagraph(nd)) return nd; return this.paragraphOf(nd.parentElement); }; KFEngine.prototype.hardBlockOf = function (nd) { if (!nd) return null; if (this.isHardBlock(nd)) return nd; return this.hardBlockOf(nd.parentElement); }; KFEngine.prototype.lcaOf = function (nd1, nd2) { var track1 = []; var track2 = []; var rootNode = this.editor.$content.parentElement; while (nd1 && nd1 !== rootNode) { track1.unshift(nd1); nd1 = nd1.parentElement; } while (nd2 && nd2 !== rootNode) { track2.unshift(nd2); nd2 = nd2.parentElement; } var res = null; for (var i = 0; i < track1.length && i < track2.length; ++i) { if (track1[i] === track2[i]) res = track1[i];else break; } return res; }; KFEngine.prototype.breakTextNode = function (textNode, offset) { var parent = (0, _FCore.$)(textNode.parentElement); var text = textNode.data; var newTextNode = (0, _FCore._)({ text: text.substring(offset) }); textNode.data = text.substring(0, offset); parent.addChildAfter(newTextNode, textNode); return newTextNode; }; KFEngine.prototype.breakElement = function (elt, offset) { var parent = (0, _FCore.$)(elt.parentElement); var newElt = elt.cloneNode(false); var rightChildren = Array.prototype.slice.call(elt.childNodes, offset); for (var i = 0; i < rightChildren.length; ++i) { newElt.appendChild(rightChildren[i]); } parent.addChildAfter(newElt, elt); return newElt; }; /** * * @param nd * @param offset * @returns {AElement|Text} - new created node */ KFEngine.prototype.breakNode = function (nd, offset) { if (this.isTextNode(nd)) { return this.breakTextNode(nd, offset); } else { return this.breakElement(nd, offset); } }; KFEngine.prototype.removeContentNode = function (nd) { if (this.isTextNode(nd)) { nd.remove(); } else if (this.isInnerBlock(nd)) { Array.prototype.slice.call(nd.childNodes).forEach(cnd => this.removeContentNode(cnd)); } else { nd.remove(); } }; KFEngine.prototype.trimLeftTextNode = function (textNode, offset) { var text = textNode.data; text = text.substring(offset); textNode.data = text; }; KFEngine.prototype.trimLeftElement = function (elt, offset) { for (var i = offset - 1; i >= 0; --i) { if (elt.childNodes[i]) this.removeContentNode(elt.childNodes[i]); } }; KFEngine.prototype.trimLeftNode = function (nd, offset) { if (this.isTextNode(nd)) return this.trimLeftTextNode(nd, offset); return this.trimLeftElement(nd, offset); }; KFEngine.prototype.trimRightTextNode = function (textNode, offset) { var text = textNode.data; text = text.substring(0, offset); textNode.data = text; }; KFEngine.prototype.trimRightElement = function (elt, offset) { for (var i = elt.childNodes.length - 1; i >= offset; --i) if (elt.childNodes[i]) this.removeContentNode(elt.childNodes[i]); }; KFEngine.prototype.trimRightNode = function (nd, offset) { if (nd.nodeType === Node.TEXT_NODE) return this.trimRightTextNode(nd, offset); return this.trimRightElement(nd, offset); }; KFEngine.prototype.trimInTextNode = function (textNode, startOffset, endOffset) { var text = textNode.data; text = text.substring(0, startOffset) + text.substring(endOffset); textNode.data = text; }; KFEngine.prototype.trimInElement = function (elt, startOffset, endOffset) { Array.prototype.slice.call(elt.childNodes, startOffset, endOffset).map(nd => nd.remove()); }; KFEngine.prototype.trimNode = function (nd, startOffset, endOffset) { if (this.isTextNode(nd)) return this.trimInTextNode(nd, startOffset, endOffset);else return this.trimInElement(nd, startOffset, endOffset); }; /** * joint element and handle range * @param elt1 * @param elt2 */ KFEngine.prototype.join2Elements = function (elt1, elt2) { if (!elt1 || !elt2) return; if (this.isHardBlock(elt1) || this.isHardBlock(elt2)) return; //can not merge var ranges = this.getRanges(); var range = ranges && ranges[0]; var startCtn = range && range.startContainer; var endCtn = range && range.endContainer; var startOffset = range && range.startOffset; var endOffset = range && range.endOffset; var rangeChanged = false; var parent = elt1.parentElement; var br; var elt1Idx = childIndexOf(elt1); if (this.isParagraph(elt1)) { //move range if (range && startCtn === parent) { if (startOffset === elt1Idx + 1) { rangeChanged = true; startCtn = elt1; startOffset = elt1.childNodes.length; } else if (startOffset > elt1Idx + 1) { rangeChanged = true; startOffset--; } } if (range && endCtn === parent) { if (endOffset === elt1Idx + 1) { rangeChanged = true; endCtn = elt1; endOffset = elt1.childNodes.length; } else if (endOffset > elt1Idx + 1) { rangeChanged = true; endOffset--; } } if (this.isParagraph(elt2)) { (0, _FCore.$)(elt1); while (elt2.firstChild) { elt1.addChild(elt2.firstChild); } elt2.remove(); } else { //span, textnode... (0, _FCore.$)(elt1); elt1.appendChild(elt2); } } else { if (this.isParagraph(elt2)) { br = (0, _FCore._)('br'); (0, _FCore.$)(parent).addChildAfter(br, elt1); if (range && startCtn === parent && startOffset > elt1Idx + 1) { startOffset += elt2.childNodes.length; //include br - el2 removed } if (range && endCtn === parent && endOffset > elt1Idx + 1) { endOffset += elt2.childNodes.length; } while (elt2.firstChild) { parent.addChildBefore(elt2.firstChild, br); } elt2.remove(); } else {//nothing to do } } if (range && rangeChanged) { range = document.createRange(); range.setStart(startCtn, startOffset); range.setEnd(endCtn, endOffset); this.setRanges([range]); } }; KFEngine.prototype.formatKeys = ['fontSize', 'color', 'fontWeight', 'fontStyle']; KFEngine.prototype.fontWeightMapping = { 100: 'thin', 200: 'extra-light', 300: 'light', 400: 'normal', 500: 'medium', 600: 'semi-bold', 700: 'bold', 800: 'extra-bold', 900: 'black' }; /** * * @param {Text|AElement} nd * @param {boolean=} depth */ KFEngine.prototype.computeNodeFormat = function (nd, depth) { if (this.isTextNode(nd)) return this.computeNodeFormat(nd.parentElement); //todo: exclude some type of element var ndStyle = getComputedStyle(nd); var rule = this.ruleOfNode(nd); var formatKeys = rule.formatKeys || this.formatKeys; var res = formatKeys.reduce((ac, key) => { ac[key] = ndStyle[key]; return ac; }, {}); if (depth) { Array.prototype.filter.call(nd.childNodes, c => !this.isTextNode(c)).forEach(c => { var cStyle = this.computeNodeFormat(c, depth); var t = Object.assign({}, res, cStyle); Object.keys(res).forEach(key => { if (cStyle[key] !== res[key]) { if (res[key]) { if (cStyle[key]) res[key] = '*'; } else { res[key] = cStyle[key]; } } }); }); } if (res.fontWeight && this.fontWeightMapping[res.fontWeight]) res.fontWeight = this.fontWeightMapping[res.fontWeight]; return res; }; /** * compare 2 node can merge,.. * @param nd1 * @param nd2 * @returns {boolean} */ KFEngine.prototype.compareFormat = function (nd1, nd2) { if (nd1.tagName !== nd2.tagName) return false; var rule1 = this.ruleOfNode(nd1); var rule2 = this.ruleOfNode(nd2); if (rule1.type !== rule2.type) return false; if (rule1.type === 'text') return true; var t1 = nd1.attributes; var t2 = nd2.attributes; if (t1.length !== t2.length) return false; var i; for (i = 0; i < t1.length; ++i) { if (t1[i].nodeValue !== t2[t1[i].nodeName].nodeValue) return false; } t1 = nd1.style; t2 = nd2.style; if (t1.length !== t2.length) return false; for (i = 0; i < t1.length; ++i) { if (t1[t1[i]] !== t2[t1[i]]) return false; } return true; }; /** * * @param {AElement|Node=} nd */ KFEngine.prototype.normalizeContent = function (nd) { var ranges = this.getRanges(); var range = ranges && ranges[0]; var startCtn, endCtn, startOffset, endOffset; if (range) { startCtn = range.startContainer; endCtn = range.endContainer; startOffset = range.startOffset; endOffset = range.endOffset; } var canMerge = (e1, e2) => { var t1 = e1.attributes; var t2 = e2.attributes; if (t1.length !== t2.length) return false; var i; for (i = 0; i < t1.length; ++i) { if (t1[i].nodeValue !== t2[t1[i].nodeName].nodeValue) return false; } t1 = e1.style; t2 = e2.style; if (t1.length !== t2.length) return false; for (i = 0; i < t1.length; ++i) { if (t1[t1[i]] !== t2[t1[i]]) return false; } return true; }; nd = nd || this.editor.$content; var visit = cNode => { var cRule = this.ruleOfNode(cNode); if (cRule.type === 'text') return; var child, nextChild, allow; for (var i = cNode.childNodes.length - 1; i >= 0; --i) { child = cNode.childNodes[i]; allow = true; if (cRule.allowChildren) { if (this.isTextNode(child)) { allow = cRule.allowChildren.indexOf('text') >= 0; } else { allow = cRule.allowChildren.some(selector => child.matches(selector)); } } if (!allow) { child.remove(); continue; } if (this.isTextNode(child)) { if (child.data.length === 0) { child.remove(); continue; } } nextChild = cNode.childNodes[i + 1]; if (nextChild) { if (this.isTextNode(child) && this.isTextNode(nextChild)) { child.data += nextChild.data; nextChild.remove(); } else if (child.tagName === nextChild.tagName && ['SPAN', 'STRONG', 'I'].indexOf(child.tagName) >= 0) { if (this.compareFormat(child, nextChild)) { while (nextChild.firstChild) { child.appendChild(nextChild.firstChild); } nextChild.remove(); } } } visit(child); if (['SPAN', 'STRONG', 'I'].indexOf(child.tagName) >= 0 && child.childNodes.length === 0) child.remove(); } if (cRule.empty && cNode.childNodes.length === 0) { cNode.appendChild((0, _FCore._)(cRule.empty)); } }; visit(nd); if (!range) return; if (startCtn !== range.startContainer || endCtn !== range.endContainer || startOffset !== range.startOffset || endCtn !== range.endContainer) { range = document.createRange(); range.setStart(startCtn, startOffset); range.setEnd(endCtn, endOffset); this.ranges = [range]; if (document.activeElement === this.editor.$content) this.focusRanges(); } }; /** *@param data * @param {Range=} range */ KFEngine.prototype.insert = function (data, range) { range = range || (this.getRanges() || [])[0]; if (range) this.deleteContentAtCurrentSelection(); range = range || (this.getRanges() || [])[0]; console.log(range); if (Array.isArray(data)) {} }; /** *@param {string} key *@param {string|null} value * @param {Range=} range * @returns {{}} */ KFEngine.prototype.formatRange = function (key, value, range) { range = range || (this.getRanges() || [])[0]; if (!range) return {}; var rangeStartCtn = range.startContainer; var rangeEndCtn = range.endContainer; var rangeStartOffset = range.startOffset; var rangeEndOffset = range.endOffset; var removeInlineStyle = (nd, key, value) => { if (!nd) return; if (this.isTextNode(nd)) return; if (nd.style[key] === value) { nd.style[key] = null; } Array.prototype.forEach.call(nd.childNodes, c => removeInlineStyle(c, key, value)); }; var unwrapDown = (nd, selector) => { if (!nd.matches) return; var childNodes = Array.prototype.slice.call(nd.childNodes); if (nd.matches(selector)) { childNodes.forEach(c => nd.parentElement.insertBefore(c, nd)); nd.remove(); } childNodes.forEach(c => unwrapDown(c, selector)); }; var paragraphsIn = (elt, res) => { res = res || []; if (this.isTextNode(elt)) return res; var ds = getComputedStyle(elt).getPropertyValue('display'); if (['table', 'block', 'grid'].indexOf(ds) >= 0) { res.push(elt); } else { Array.prototype.forEach.call(elt.childNodes, c => paragraphsIn(c, res)); } return res; }; var paragraphBetween = (startElt, endElt, res) => { res = res || []; var lcaElt = this.lcaOf(startElt, endElt); return res; }; var autoMerge = cNode => { var nextChild, child; for (var i = cNode.childNodes.length - 1; i >= 0; --i) { nextChild = cNode.childNodes[i + 1]; child = cNode.childNodes[i]; if (nextChild && this.compareFormat(child, nextChild) || isInline(child)) { if (this.isTextNode(child)) { if (rangeStartCtn === nextChild) { rangeStartCtn = child; rangeStartOffset += child.data.length; } if (rangeEndCtn === nextChild) { rangeEndCtn = child; rangeEndOffset += child.data.length; } child.data += nextChild.data; } else { if (rangeStartCtn === nextChild) { rangeStartCtn = child; rangeStartOffset += child.childNodes.length; } if (rangeEndCtn === nextChild) { rangeEndCtn = child; rangeEndOffset += child.childNodes.length; } while (nextChild.firstChild) { child.appendChild(nextChild.firstChild); } } nextChild.remove(); } autoMerge(child); } }; var isInline = node => { if (node.nodeType === Node.TEXT_NODE) return true; var cStyle = getComputedStyle(node); var dp = cStyle.getPropertyValue('display'); return dp.indexOf('inline') >= 0; }; var wrapContent = (nodes, tag) => { if (!nodes.length) return; var parent = nodes[0].parentElement; var rangeEndOffsetNode; if (!this.isTextNode(rangeEndCtn)) rangeEndOffsetNode = rangeEndCtn.childNodes[rangeEndOffset]; //todo: modify range var newNode = null; var i, nd; for (i = 0; i < nodes.length; ++i) { nd = nodes[i]; if (isInline(nd)) { if (!newNode) { newNode = (0, _FCore._)({ tag: tag }); parent.insertBefore(newNode, nd); } newNode.appendChild(nd); unwrapDown(nd, tag); } else { newNode = null; wrapContent(Array.prototype.slice.call(nd.childNodes), tag); } } if (!this.isTextNode(rangeEndCtn)) { if (rangeEndOffsetNode) { rangeEndOffset = childIndexOf(rangeEndOffsetNode); } else { rangeEndOffset = rangeEndCtn.childNodes.length; } } }; var sFormat = (startNode, startOffset, endNode, endOffset, opt) => { var lcaNode = this.lcaOf(startNode, endNode); var paragraph = this.paragraphOf(lcaNode); var hardBlock = this.hardBlockOf(lcaNode); var ctn = paragraph || hardBlock; var ctnStyle = this.computeNodeFormat(ctn); if (ctnStyle[opt.key] === opt.value) { //normalize children only unwrapDown(ctn, opt.wrapTag); Array.prototype.forEach.call(ctn.childNodes, c => removeInlineStyle(c, opt.key, opt.value)); return; } var startBoundElt = this.paragraphOf(startNode) || this.hardBlockOf(startNode); var endBoundElt = this.paragraphOf(endNode) || this.hardBlockOf(endNode); var curNode, curOffset, newNode, newChildren; var fStartCtn, fEndCtn; var fStartOffset, fEndOffset; var endOffsetNode; if (startBoundElt === endBoundElt) { endOffsetNode = endNode.childNodes[endOffset]; curNode = startNode; curOffset = startOffset; while (curNode !== lcaNode) { if (curOffset === 0) { curOffset = childIndexOf(curNode); } else { newNode = this.breakNode(curNode, curOffset); if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) { rangeStartCtn = newNode; rangeStartOffset -= curOffset; } curOffset = childIndexOf(newNode); if (endNode === newNode.parentElement && endOffset >= curOffset) { endOffset++; } } curNode = curNode.parentElement; } fStartOffset = curOffset; curNode = endNode; curOffset = endOffset; while (curNode !== lcaNode) { if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) { curOffset = childIndexOf(curNode) + 1; } else { newNode = this.breakNode(curNode, curOffset); if (rangeEndCtn === curNode && rangeEndOffset > curOffset) { rangeEndCtn = newNode; rangeEndOffset -= curOffset; } curOffset = childIndexOf(newNode); } curNode = curNode.parentElement; } fEndOffset = curOffset; if (this.isTextNode(lcaNode)) { if (fEndOffset < lcaNode.data.length) { newNode = (0, _FCore._)({ text: lcaNode.data.substring(fEndOffset) }); lcaNode.parentElement.insertBefore(newNode, lcaNode.nextSibling); if (rangeEndCtn === lcaNode && rangeEndOffset > fEndOffset) { rangeEndOffset -= fEndOffset; rangeEndCtn = newNode; } } if (fStartOffset > 0) { newNode = (0, _FCore._)({ text: lcaNode.data.substring(0, rangeStartOffset) }); lcaNode.parentElement.insertBefore(newNode, lcaNode); if (rangeStartCtn === lcaNode) { if (rangeStartOffset < fStartOffset) { rangeStartCtn = newNode; } else { rangeStartOffset -= fStartOffset; } } if (rangeEndCtn === lcaNode) { rangeEndOffset -= fStartOffset; } } lcaNode.data = lcaNode.data.substring(fStartOffset, fEndOffset); newNode = (0, _FCore._)({ tag: opt.wrapTag }); lcaNode.parentElement.replaceChild(newNode, lcaNode); newNode.appendChild(lcaNode); } else { newChildren = Array.prototype.slice.call(lcaNode.childNodes, fStartOffset, fEndOffset); wrapContent(newChildren, opt.wrapTag); } // autoMerge(lcaNode); } else if (_AElement.default.prototype.isDescendantOf.call(startBoundElt, endBoundElt)) { endOffsetNode = endNode.childNodes[endOffset]; curNode = startNode; curOffset = startOffset; while (curNode !== startBoundElt) { if (curOffset === 0) { curOffset = childIndexOf(curNode); } else { newNode = this.breakNode(curNode, curOffset); if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) { rangeStartCtn = newNode; rangeStartOffset -= curOffset; } curOffset = childIndexOf(newNode); } curNode = curNode.parentElement; } fStartCtn = startBoundElt; fStartOffset = curOffset; newChildren = Array.prototype.slice.call(fStartCtn.childNodes, fStartOffset); wrapContent(newChildren, opt.wrapTag); curOffset = childIndexOf(startBoundElt) + 1; curNode = startBoundElt.parentElement; while (curNode !== lcaNode) { if (curOffset < curNode.childNodes.length) break; curOffset = childIndexOf(curNode); curNode = curNode.parentElement; } startNode = curNode; startOffset = curOffset; if (endOffsetNode) { endOffset = childIndexOf(endOffsetNode); } else { endOffset = endNode.childNodes.length; } if (startNode !== endNode || startOffset < endOffset) { sFormat(startNode, startOffset, endNode, endOffset, opt); } } else if (_AElement.default.prototype.isDescendantOf.call(endBoundElt, startBoundElt)) { curNode = endNode; curOffset = endOffset; while (curNode !== endBoundElt) { if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) { curOffset = childIndexOf(curNode) + 1; } else { newNode = this.breakNode(curNode, curOffset); if (rangeEndCtn === curNode && rangeEndOffset > curOffset) { rangeEndCtn = newNode; rangeEndOffset -= curOffset; } curOffset = childIndexOf(newNode); if (endNode === newNode.parentElement && endOffset >= curOffset) { endOffset++; } } curNode = curNode.parentElement; } fEndOffset = curOffset; fEndCtn = endBoundElt; newChildren = Array.prototype.slice.call(fEndCtn.childNodes, 0, fEndOffset); wrapContent(newChildren, opt.wrapTag); curOffset = childIndexOf(endBoundElt); curNode = endBoundElt.parentElement; while (curNode !== lcaNode) { if (curOffset > 0) break; curOffset = childIndexOf(curNode); curNode = curNode.parentElement; } endNode = curNode; endOffset = curOffset; // console.log(startNode.cloneNode(true), startOffset, endNode.cloneNode(true), endOffset) // if (startNode !== endNode || startOffset < endOffset) { sFormat(startNode, startOffset, endNode, endOffset, opt); } } else { curNode = startNode; curOffset = startOffset; while (curNode !== startBoundElt) { if (curOffset === 0) { curOffset = childIndexOf(curNode); } else { newNode = this.breakNode(curNode, curOffset); if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) { rangeStartCtn = newNode; rangeStartOffset -= curOffset; } curOffset = childIndexOf(newNode); if (endNode === newNode.parentElement && endOffset >= curOffset) { endOffset++; } } curNode = curNode.parentElement; } fStartOffset = curOffset; fStartCtn = startBoundElt; newChildren = Array.prototype.slice.call(fStartCtn.childNodes, fStartOffset); wrapContent(newChildren, opt.wrapTag); curNode = endNode; curOffset = endOffset; while (curNode !== endBoundElt) { if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) { curOffset = childIndexOf(curNode) + 1; } else { newNode = this.breakNode(curNode, curOffset); if (rangeEndCtn === curNode && rangeEndOffset > curOffset) { rangeEndCtn = newNode; rangeEndOffset -= curOffset; } curOffset = childIndexOf(newNode); } curNode = curNode.parentElement; } fEndOffset = curOffset; fEndCtn = endBoundElt; newChildren = Array.prototype.slice.call(fEndCtn.childNodes, 0, fEndOffset); newNode = (0, _FCore._)({ tag: opt.wrapTag }); fEndCtn.insertBefore(newNode, fEndCtn.firstChild); newChildren.forEach(c => newNode.appendChild(c)); newChildren.forEach(c => unwrapDown(c, opt.wrapTag)); lcaNode = this.lcaOf(startBoundElt, endBoundElt); //find between curOffset = childIndexOf(startBoundElt) + 1; curNode = startBoundElt.parentElement; while (curNode !== lcaNode) { if (curOffset < curNode.childNodes.length) break; curOffset = childIndexOf(curNode) + 1; curNode = curNode.parentElement; } startNode = curNode; startOffset = curOffset; curOffset = childIndexOf(endBoundElt); curNode = endBoundElt.parentElement; while (curNode !== lcaNode) { if (curOffset > 0) break; curOffset = childIndexOf(curNode); curNode = curNode.parentElement; } endNode = curNode; endOffset = curOffset; if (startNode !== endNode || startOffset < endOffset) { sFormat(startNode, startOffset, endNode, endOffset, opt); } } }; var bold = () => { sFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, { wrapTag: 'strong', key: 'fontWeight', value: 'bold' }); }; var italic = () => { sFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, { wrapTag: 'i', key: 'fontStyle', value: 'italic' }); }; var alignFormat = (startNode, startOffset, endNode, endOffset, value) => { var lca = this.lcaOf(startNode, endNode); var boundElt = this.paragraphOf(lca) || this.hardBlockOf(lca); var rangeEndOffsetNode, rangeStartOffsetNode; if (!this.isTextNode(rangeStartCtn)) rangeStartOffsetNode = rangeStartCtn.childNodes[rangeStartOffset]; if (!this.isTextNode(rangeEndCtn)) rangeEndOffsetNode = rangeEndCtn.childNodes[rangeEndOffset]; var newChildren, child, newNode, i; if (boundElt === this.editor.$content) { while (startNode !== boundElt) { startOffset = childIndexOf(startNode); startNode = startNode.parentElement; } while (endNode !== boundElt) { endOffset = childIndexOf(endNode) + 1; endNode = endNode.parentElement; } if (isInline(boundElt.childNodes[startOffset])) { while (boundElt.childNodes[startOffset - 1] && boundElt.childNodes[startOffset - 1].tagName !== 'BR' && isInline(boundElt.childNodes[startOffset - 1])) startOffset--; } if (isInline(boundElt.childNodes[endOffset - 1])) { while (boundElt.childNodes[endOffset] && boundElt.childNodes[endOffset].tagName !== 'BR' && isInline(boundElt.childNodes[endOffset])) endOffset++; } newChildren = Array.prototype.slice.call(boundElt.childNodes, startOffset, endOffset); newNode = null; for (i = 0; i < newChildren.length; ++i) { child = newChildren[i]; if (isInline(child)) { if (!newNode) { newNode = (0, _FCore._)({ tag: 'p', style: { textAlign: value } }); boundElt.insertBefore(newNode, child); } newNode.appendChild(child); } else { newNode = null; child.style.textAlign = value; } } } else { boundElt.style.textAlign = value; } if (!this.isTextNode(rangeStartCtn)) { if (rangeStartOffsetNode) { rangeStartOffset = childIndexOf(rangeStartOffsetNode); rangeStartCtn = rangeStartOffsetNode.parentElement; } else { rangeStartOffset = rangeStartCtn.childNodes.length; } } if (!this.isTextNode(rangeEndCtn)) { if (rangeEndOffsetNode) { rangeEndOffset = childIndexOf(rangeEndOffsetNode); rangeEndCtn = rangeEndOffsetNode.parentElement; } else { rangeEndOffset = rangeEndCtn.childNodes.length; } } }; if (key === 'fontWeight') { if (value === 'bold') { bold(); } else {} } else if (key === 'fontStyle') { if (value === 'italic') { italic(); } } else if (key === 'textAlign') { alignFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, value); } var unwrapUp = (nd, selector) => { if (!nd) return; if (nd.contenteditable) return; unwrapUp(nd.parentElement, selector); if (!nd.matches) return; var childNodes; if (nd.matches(selector)) { childNodes = Array.prototype.slice.call(nd.childNodes); childNodes.forEach(c => nd.parentElement.insertBefore(c, nd)); nd.remove(); } }; if (rangeStartOffset !== range.startOffset || rangeEndOffset !== rangeEndOffset || rangeStartCtn !== range.startContainer || rangeEndCtn !== range.endContainer) { range = document.createRange(); range.setStart(rangeStartCtn, rangeStartOffset); range.setEnd(rangeEndCtn, rangeEndOffset); this.setRanges(range); } }; /** * * @param {Range} range * @returns {{}} */ KFEngine.prototype.computeRangeFormat = function (range) { range = range || (this.getRanges() || [])[0]; if (!range) return {}; if (range.collapsed) return this.computeNodeFormat(range.startContainer); var startCtn = range.startContainer; var arr = []; var startOffset = range.startOffset; var endCtn = range.endContainer; var endOffset = range.endOffset; var lcaNode = this.lcaOf(startCtn, endCtn); var lcaStartOffset, lcaEndOffset; var curNode = startCtn; var offset = startOffset; var sArr; while (curNode !== lcaNode) { // this.trimRightNode(curNode, offset); if (this.isTextNode(curNode)) { arr.push(this.computeNodeFormat(curNode)); } else { sArr = Array.prototype.slice.call(curNode.childNodes, offset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true)); arr = arr.concat(sArr); } offset = childIndexOf(curNode) + 1; curNode = curNode.parentElement; } lcaStartOffset = offset; curNode = endCtn; offset = endOffset; while (curNode !== lcaNode) { // this.trimLeftNode(curNode, offset); if (this.isTextNode(curNode)) { arr.push(this.computeNodeFormat(curNode)); } else { sArr = Array.prototype.slice.call(curNode.childNodes, 0, offset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true)); arr = arr.concat(sArr); } offset = childIndexOf(curNode); curNode = curNode.parentElement; } lcaEndOffset = offset; if (this.isTextNode(lcaNode) || lcaStartOffset === lcaEndOffset) { return this.computeNodeFormat(lcaNode); } else { sArr = Array.prototype.slice.call(lcaNode.childNodes, lcaStartOffset, lcaEndOffset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true)); arr = arr.concat(sArr); return arr.slice(1).reduce((ac, cr) => { Object.keys(ac).forEach(key => { if (cr[key] !== ac[key]) { delete ac[key]; } }); return ac; }, arr[0]); } }; KFEngine.prototype.deleteContentAtCurrentSelection = function () { var ranges = this.getRanges(); if (!ranges) return; var range = ranges[0]; if (range.collapsed) return; var startCtn = range.startContainer; var startOffset = range.startOffset; var endCtn = range.endContainer; var endOffset = range.endOffset; var lcaNode = this.lcaOf(startCtn, endCtn); var lcaStartOffset, lcaEndOffset; var curNode = startCtn; var offset = startOffset; while (curNode !== lcaNode) { this.trimRightNode(curNode, offset); offset = childIndexOf(curNode) + 1; curNode = curNode.parentElement; } lcaStartOffset = offset; curNode = endCtn; offset = endOffset; while (curNode !== lcaNode) { this.trimLeftNode(curNode, offset); offset = childIndexOf(curNode); curNode = curNode.parentElement; } lcaEndOffset = offset; var inRangeNodes; if (this.isTextNode(lcaNode)) { this.trimInTextNode(lcaNode, lcaStartOffset, lcaEndOffset); } else { inRangeNodes = Array.prototype.slice.call(lcaNode.childNodes, lcaStartOffset, lcaEndOffset); inRangeNodes.forEach(it => this.removeContentNode(it)); } endOffset = lcaStartOffset; startOffset = lcaStartOffset; startCtn = lcaNode; endCtn = lcaNode; range = document.createRange(); range.setStart(startCtn, startOffset); range.setEnd(endCtn, endOffset); this.setRanges([range]); // /**joint**/ var leftNode = lcaNode.childNodes[startOffset - 1]; var rightNode = lcaNode.childNodes[endOffset]; this.join2Elements(leftNode, rightNode); }; KFEngine.prototype.breakParagraphAtCurrentSelection = function () { var ranges = this.getRanges(); if (!ranges) return; var range = ranges[0]; var curNode = range.startContainer; var offset = range.startOffset; console.log(curNode, offset); var newNode; if (curNode === this.editor.$content) { newNode = (0, _FCore._)('br'); if (offset >= curNode.childNodes.length) { curNode.addChild(newNode); } else { curNode.addChildAfter(newNode, curNode.childNodes[offset]); } range = document.createRange(); range.setStart(curNode, offset + 1); range.setEnd(curNode, offset + 1); this.setRanges([range]); return; } var parent = curNode.parentElement; var paragraph = this.paragraphOf(parent); var hardBlock = this.hardBlockOf(parent); var newRange; var newRangeCtn; console.log(paragraph, hardBlock); if (this.isInterior(curNode)) { newNode = (0, _FCore._)('br'); curNode.insertBefore(newNode, curNode.childNodes[offset]); offset++; if (curNode.lastChild === newNode) { curNode.appendChild((0, _FCore._)('br')); } newRange = document.createRange(); newRange.setStart(curNode, offset); this.setRanges(newRange); } else if (paragraph) { do { newNode = this.breakNode(curNode, offset); if (!newRangeCtn) { newRangeCtn = newNode; } (0, _FCore.$)(parent).addChildAfter(newNode, curNode); offset = childIndexOf(newNode); curNode = parent; parent = parent.parentElement; } while (paragraph.parentElement !== curNode); newRange = document.createRange(); newRange.setStart(newRangeCtn, 0); this.setRanges([newRange]); } else if (hardBlock) { while (curNode !== hardBlock) { newNode = this.breakNode(curNode, offset); if (!newRangeCtn) { newRangeCtn = newNode; } // $(parent).addChildAfter(newNode, curNode); offset = childIndexOf(newNode); curNode = parent; parent = parent.parentElement; } if (newNode && newNode === hardBlock.lastChild) { hardBlock.appendChild((0, _FCore._)('br')); } newNode = (0, _FCore._)('br'); curNode.addChildBefore(newNode, curNode.childNodes[offset]); newRange = document.createRange(); newRange.setStart(newRangeCtn, 0); this.setRanges([newRange]); } else { console.log("TODO", "not handle this case"); } }; KFEngine.prototype.deleteBackAtCurrentSelection = function () { var ranges = this.getRanges(); if (!ranges) return; var range = ranges[0]; var startCtn = range.startContainer; var startOffset = range.startOffset; var endCtn = range.endContainer; var endOffset = range.endOffset; var moveBack = () => { var prevNode; if (this.isTextNode(startCtn)) { if (startOffset > 0) { startOffset--; return false; } else { startOffset = childIndexOf(startCtn); startCtn = startCtn.parentElement; return true; } } else { if (startOffset > 0) { prevNode = startCtn.childNodes[startOffset - 1]; if (this.isVoid(prevNode)) { startOffset--; return false; } else if (this.isTextNode(prevNode)) { startCtn = prevNode; startOffset = prevNode.data.length; return true; } else if (this.isParagraph(prevNode)) { startCtn = prevNode; startOffset = prevNode.childNodes.length; return false; } else { startCtn = prevNode; startOffset = prevNode.childNodes.length; return true; } } else { startOffset = childIndexOf(startCtn); startCtn = startCtn.parentElement; return true; } } }; while (moveBack()) {} var startHardBlock = this.hardBlockOf(startCtn); var endHardBlock = this.hardBlockOf(endCtn); if (startHardBlock !== endHardBlock) return; range = document.createRange(); range.setStart(startCtn, startOffset); range.setEnd(endCtn, endOffset); this.ranges = [range]; //set ranges without view this.deleteContentAtCurrentSelection(); }; KFEngine.prototype.getData = function () { var data = {}; var range = (this.getRanges() || [])[0]; var startCtn, startOffset; var endCtn, endOffset; if (range) { startCtn = range.startContainer; startOffset = range.startOffset; endCtn = range.endContainer; endOffset = range.endOffset; } var hash = 0; var makeDescriptor = nd => { var res = {}; if (nd === startCtn) { res.rangeStartOffset = startOffset; } if (nd === endCtn) { res.rangeEndOffset = endOffset; } var i, atrNode; if (nd.nodeType === Node.TEXT_NODE) { res.text = nd.data; hash = hash + (0, _stringUtils.stringHashCode)(res.text) & 0xffff; } else { res.tag = nd.tagName.toLowerCase(); hash = hash + (0, _stringUtils.stringHashCode)(res.tag) & 0xffff; if (nd.style.length > 0) { res.style = {}; for (i = 0; i < nd.style.length; ++i) { res.style[nd.style[i]] = nd.style[nd.style[i]]; hash = hash + (0, _stringUtils.stringHashCode)(nd.style[i] + res.style[nd.style[i]]) & 0xffff; } } if (nd.attributes.length > 0) { res.attr = {}; for (i = 0; i < nd.attributes.length; ++i) { atrNode = nd.attributes[i]; res.attr[atrNode.nodeName] = atrNode.nodeValue; } } if (nd.childNodes.length > 0) { res.child = Array.prototype.map.call(nd.childNodes, e => makeDescriptor(e)); } } return res; }; data.child = Array.prototype.map.call(this.editor.$content.childNodes, e => makeDescriptor(e)); data.hash = hash; return data; }; KFEngine.prototype.setData = function (data) { data = data || {}; var startCtn, startOffset; var endCtn, endOffset; var range; var build = data => { var res; if (typeof data.text === "string") { res = (0, _FCore._)({ text: data.text }); } else { res = (0, _FCore._)({ tag: data.tag, style: data.style || {}, attr: data.attr || {} }); } if (typeof data.rangeStartOffset === "number") { startCtn = res; startOffset = data.rangeStartOffset; } if (typeof data.rangeEndOffset === "number") { endCtn = res; endOffset = data.rangeEndOffset; } if (Array.isArray(data.child)) { res.addChild(data.child.map(d => build(d))); } return res; }; this.editor.$content.clearChild(); if (Array.isArray(data.child)) { this.editor.$content.addChild(data.child.map(d => build(d))); } if (startCtn) { range = document.createRange(); range.setStart(startCtn, startOffset); if (endCtn) { range.setEnd(endCtn, endOffset); } this.setRanges(range); } }; var _default = KFEngine; exports.default = _default;