selection-ranges
Advanced tools
| {"version":3,"file":"index.js","sources":["../node_modules/component-xor/index.js","../node_modules/component-props/index.js","../node_modules/dom-iterator/index.js","../lib/index.js"],"sourcesContent":["/**\n * Expose `xor`\n */\n\nmodule.exports = xor;\n\n/**\n * XOR utility\n *\n * T T F\n * T F T\n * F T T\n * F F F\n *\n * @param {Boolean} a\n * @param {Boolean} b\n * @return {Boolean}\n */\n\nfunction xor(a, b) {\n return a ^ b;\n}\n","/**\n * Global Names\n */\n\nvar globals = /\\b(Array|Date|Object|Math|JSON)\\b/g;\n\n/**\n * Return immediate identifiers parsed from `str`.\n *\n * @param {String} str\n * @param {String|Function} map function or prefix\n * @return {Array}\n * @api public\n */\n\nmodule.exports = function(str, fn){\n var p = unique(props(str));\n if (fn && 'string' == typeof fn) fn = prefixed(fn);\n if (fn) return map(str, p, fn);\n return p;\n};\n\n/**\n * Return immediate identifiers in `str`.\n *\n * @param {String} str\n * @return {Array}\n * @api private\n */\n\nfunction props(str) {\n return str\n .replace(/\\.\\w+|\\w+ *\\(|\"[^\"]*\"|'[^']*'|\\/([^/]+)\\//g, '')\n .replace(globals, '')\n .match(/[a-zA-Z_]\\w*/g)\n || [];\n}\n\n/**\n * Return `str` with `props` mapped with `fn`.\n *\n * @param {String} str\n * @param {Array} props\n * @param {Function} fn\n * @return {String}\n * @api private\n */\n\nfunction map(str, props, fn) {\n var re = /\\.\\w+|\\w+ *\\(|\"[^\"]*\"|'[^']*'|\\/([^/]+)\\/|[a-zA-Z_]\\w*/g;\n return str.replace(re, function(_){\n if ('(' == _[_.length - 1]) return fn(_);\n if (!~props.indexOf(_)) return _;\n return fn(_);\n });\n}\n\n/**\n * Return unique array.\n *\n * @param {Array} arr\n * @return {Array}\n * @api private\n */\n\nfunction unique(arr) {\n var ret = [];\n\n for (var i = 0; i < arr.length; i++) {\n if (~ret.indexOf(arr[i])) continue;\n ret.push(arr[i]);\n }\n\n return ret;\n}\n\n/**\n * Map with prefix `str`.\n */\n\nfunction prefixed(str) {\n return function(_){\n return str + _;\n };\n}\n","/**\n * Module Dependencies\n */\n\nvar xor = require('component-xor');\nvar props = require('component-props');\n\n\n/**\n * Export `Iterator`\n */\n\nmodule.exports = Iterator;\n\n/**\n * Initialize `Iterator`\n *\n * @param {Node} node\n * @param {Node} root\n * @return {Iterator} self\n * @api public\n */\n\nfunction Iterator(node, root) {\n if (!(this instanceof Iterator)) return new Iterator(node, root);\n this.node = this.start = this.peeked = node;\n this.root = root;\n this.closingTag = false;\n this._revisit = true;\n this._selects = [];\n this._rejects = [];\n\n if (node && this.higher(node)) {\n throw new Error('root must be a parent or ancestor to node');\n }\n}\n\n/**\n * Reset the Iterator\n *\n * @param {Node} node (optional)\n * @return {Iterator} self\n * @api public\n */\n\nIterator.prototype.reset = function(node) {\n this.node = node || this.start;\n return this;\n};\n\n/**\n * Revisit element nodes. Defaults to `true`\n */\n\nIterator.prototype.revisit = function(revisit) {\n this._revisit = undefined == revisit ? true : revisit;\n return this;\n};\n\n/**\n * Jump to the opening tag\n */\n\nIterator.prototype.opening = function() {\n if (1 == this.node.nodeType) this.closingTag = false;\n return this;\n};\n\n/**\n * Jump to the closing tag\n */\n\nIterator.prototype.atOpening = function() {\n return !this.closingTag;\n};\n\n\n/**\n * Jump to the closing tag\n */\n\nIterator.prototype.closing = function() {\n if (1 == this.node.nodeType) this.closingTag = true;\n return this;\n};\n\n/**\n * Jump to the closing tag\n */\n\nIterator.prototype.atClosing = function() {\n return this.closingTag;\n};\n\n/**\n * Next node\n *\n * @param {Number} type\n * @return {Node|null}\n * @api public\n */\n\nIterator.prototype.next = traverse('nextSibling', 'firstChild');\n\n/**\n * Previous node\n *\n * @param {Number} type\n * @return {Node|null}\n * @api public\n */\n\nIterator.prototype.previous =\nIterator.prototype.prev = traverse('previousSibling', 'lastChild');\n\n/**\n * Make traverse function\n *\n * @param {String} dir\n * @param {String} child\n * @return {Function}\n * @api private\n */\n\nfunction traverse(dir, child) {\n var next = dir == 'nextSibling';\n return function walk(expr, n, peek) {\n expr = this.compile(expr);\n n = n && n > 0 ? n : 1;\n var node = this.node;\n var closing = this.closingTag;\n var revisit = this._revisit;\n\n while (node) {\n if (xor(next, closing) && node[child]) {\n // element with children: <em>...</em>\n node = node[child];\n closing = !next;\n } else if (1 == node.nodeType && !node[child] && xor(next, closing)) {\n // empty element tag: <em></em>\n closing = next;\n if (!revisit) continue;\n } else if (node[dir]) {\n // element has a neighbor: ...<em></em>...\n node = node[dir];\n closing = !next;\n } else {\n // done with current layer, move up.\n node = node.parentNode;\n closing = next;\n if (!revisit) continue;\n }\n\n if (!node || this.higher(node, this.root)) break;\n\n if (expr(node) && this.selects(node, peek) && this.rejects(node, peek)) {\n if (--n) continue;\n if (!peek) this.node = node;\n this.closingTag = closing;\n return node;\n }\n }\n\n return null;\n };\n}\n\n/**\n * Select nodes that cause `expr(node)`\n * to be truthy\n *\n * @param {Number|String|Function} expr\n * @return {Iterator} self\n * @api public\n */\n\nIterator.prototype.select = function(expr) {\n expr = this.compile(expr);\n this._selects.push(expr);\n return this;\n};\n\n/**\n * Run through the selects ORing each\n *\n * @param {Node} node\n * @param {Boolean} peek\n * @return {Boolean}\n * @api private\n */\n\nIterator.prototype.selects = function(node, peek) {\n var exprs = this._selects;\n var len = exprs.length;\n if (!len) return true;\n\n for (var i = 0; i < len; i++) {\n if (exprs[i].call(this, node, peek)) return true;\n };\n\n return false;\n};\n\n/**\n * Select nodes that cause `expr(node)`\n * to be falsy\n *\n * @param {Number|String|Function} expr\n * @return {Iterator} self\n * @api public\n */\n\nIterator.prototype.reject = function(expr) {\n expr = this.compile(expr);\n this._rejects.push(expr);\n return this;\n};\n\n/**\n * Run through the reject expressions ANDing each\n *\n * @param {Node} node\n * @param {Boolean} peek\n * @return {Boolean}\n * @api private\n */\n\nIterator.prototype.rejects = function(node, peek) {\n var exprs = this._rejects;\n var len = exprs.length;\n if (!len) return true;\n\n for (var i = 0; i < len; i++) {\n if (exprs[i].call(this, node, peek)) return false;\n };\n\n return true;\n};\n\n/**\n * Check if node is higher\n * than root.\n *\n * @param {Node} node\n * @param {Node} root\n * @return {Boolean}\n * @api private\n */\n\nIterator.prototype.higher = function(node) {\n var root = this.root;\n if (!root) return false;\n node = node.parentNode;\n while (node && node != root) node = node.parentNode;\n return node != root;\n};\n\n/**\n * Compile an expression\n *\n * @param {String|Function|Number} expr\n * @return {Function}\n */\n\nIterator.prototype.compile = function(expr) {\n switch (typeof expr) {\n case 'number':\n return function(node) { return expr == node.nodeType; };\n case 'string':\n return new Function('node', 'return ' + props(expr, 'node.'));\n case 'function':\n return expr;\n default:\n return function() { return true; };\n }\n};\n\n/**\n * Peek in either direction\n * `n` nodes. Peek backwards\n * using negative numbers.\n *\n * @param {Number} n (optional)\n * @return {Node|null}\n * @api public\n */\n\nIterator.prototype.peak =\nIterator.prototype.peek = function(expr, n) {\n if (arguments.length == 1) n = expr, expr = true;\n n = undefined == n ? 1 : n;\n if (!n) return this.node;\n else if (n > 0) return this.next(expr, n, true);\n else return this.prev(expr, Math.abs(n), true);\n};\n\n/**\n * Add a plugin\n *\n * @param {Function} fn\n * @return {Iterator}\n * @api public\n */\n\nIterator.prototype.use = function(fn) {\n fn(this);\n return this;\n};\n","/**\n * Module Dependencies\n */\n\nimport iterator from 'dom-iterator';\n\nvar selection = window.getSelection();\n\n\n/**\n * Add selection / insert cursor.\n *\n * @param {Range} range\n */\nexport function applyRange(range) {\n selection.removeAllRanges();\n selection.addRange(range);\n}\n\n\n/**\n * Get current document selection.\n *\n * @return {Selection}\n */\nexport function getWindowSelection() {\n return selection;\n}\n\n\n/**\n * Return true if element is part of window selection.\n *\n * @param {Element} el\n * @return {Boolean}\n */\nexport function isSelected(el) {\n\n if (!selection.rangeCount) {\n return null;\n }\n\n var focusNode = selection.focusNode;\n\n // IE supports Node#contains for elements only\n // thus we ensure we check against an actual Element node\n if (isText(focusNode)) {\n focusNode = focusNode.parentNode;\n }\n\n return el == focusNode || el.contains(focusNode);\n}\n\n\n/**\n * Set cursor or selection position.\n *\n * @param {Element} el\n * @param {SelectionRange} selection\n */\nexport function setRange(el, selection) {\n\n var range = createRange(el, selection);\n\n applyRange(range);\n}\n\n\n/**\n * Get cursor or selection position.\n *\n * @param {Element} el\n */\nexport function getRange(el) {\n\n if (!isSelected(el)) {\n return null;\n }\n\n var range = selection.getRangeAt(0);\n\n var startContainer = range.startContainer;\n var endContainer = range.endContainer;\n var startOffset = range.startOffset;\n var endOffset = range.endOffset;\n\n var i = iterator(el.firstChild, el);\n\n var next = i.node;\n var last;\n\n var isClosing = false;\n\n var selectionStart;\n var count = 0;\n\n function isBeforeEnd(node, referenceNode) {\n\n if (arguments.length === 1) {\n referenceNode = node;\n }\n\n return (\n node.parentNode === endContainer &&\n referenceNode == endContainer.childNodes[endOffset]\n );\n\n }\n\n function isBeforeStart(node, referenceNode) {\n\n if (arguments.length === 1) {\n referenceNode = node;\n }\n\n return (\n node.parentNode === startContainer &&\n referenceNode == startContainer.childNodes[startOffset]\n );\n\n }\n\n while (next) {\n\n // start before node\n if (isBeforeStart(next)) {\n selectionStart = count;\n }\n\n // end before node\n if (isBeforeEnd(next)) {\n break;\n }\n\n if (!isClosing) {\n if (\n isBr(next) || (\n last && (last.nextSibling == next) && (\n isDiv(next) ||\n isParagraph(next)\n )\n )\n ) {\n count++;\n }\n }\n\n\n if (isText(next)) {\n\n // #text node\n if (startContainer === next) {\n selectionStart = count + startOffset;\n }\n\n if (endContainer === next) {\n count += endOffset;\n break;\n }\n\n count += next.textContent.length;\n }\n\n if (isText(next) || isClosing) {\n\n // start before node\n if (isBeforeStart(next, next.nextSibling)) {\n selectionStart = count;\n }\n\n // end before node\n if (isBeforeEnd(next, next.nextSibling)) {\n break;\n }\n\n }\n\n last = next;\n next = i.next();\n isClosing = i.closingTag;\n }\n\n // selection until end of text\n return {\n start: typeof selectionStart === 'undefined' ? count : selectionStart,\n end: count\n };\n}\n\n\n/**\n * Annotate the given text with markers based on the\n * given range.\n *\n * @param {String} text\n * @param {SelectionRange} range\n *\n * @return {String} annotated text\n */\nexport function annotateRange(text, range) {\n var str;\n\n if (range.start === range.end) {\n str = (\n text.substring(0, range.start) +\n '|' +\n text.substring(range.start)\n );\n } else {\n str = (\n text.substring(0, range.start) +\n '<' +\n text.substring(range.start, range.end) +\n '>' +\n text.substring(range.end)\n );\n }\n\n return str;\n}\n\n\n// helpers ///////////////////////////\n\nfunction createRange(el, selection) {\n\n var start = selection.start;\n var end = selection.end;\n\n var range = document.createRange();\n\n var i = iterator(el.firstChild, el);\n\n var next = i.node;\n var isClosing = false;\n\n var count = 0;\n var length;\n\n while (next) {\n\n if (count === start) {\n if (isClosing) {\n range.setStartAfter(next);\n } else {\n range.setStartBefore(next);\n }\n }\n\n if (count === end) {\n if (isClosing) {\n range.setEndAfter(next);\n } else {\n range.setEndBefore(next);\n }\n\n return range;\n }\n\n if (!isClosing) {\n if (\n isBr(next) || (\n next.previousSibling && (\n isDiv(next) ||\n isParagraph(next)\n )\n )\n ) {\n count++;\n }\n }\n\n if (isText(next)) {\n\n length = next.textContent.length;\n\n if (count <= start && count + length > start) {\n range.setStart(next, start - count);\n }\n\n if (count + length > end) {\n range.setEnd(next, end - count);\n\n return range;\n }\n\n count += length;\n }\n\n next = i.next();\n isClosing = i.closingTag;\n }\n\n // out of range\n if (count <= start) {\n if (el.lastChild) {\n range.setStartAfter(el.lastChild);\n } else {\n range.setStart(el, 0);\n }\n }\n\n if (el.lastChild) {\n range.setEndAfter(el.lastChild);\n } else {\n range.setEnd(el, 0);\n }\n\n return range;\n}\n\nfunction isText(node) {\n return node.nodeType === 3;\n}\n\nfunction isBr(node) {\n return (\n node.nodeType === 1 &&\n node.nodeName === 'BR'\n );\n}\n\nfunction isDiv(node) {\n return (\n node.nodeType === 1 &&\n node.nodeName === 'DIV'\n );\n}\n\nfunction isParagraph(node) {\n return (\n node.nodeType === 1 &&\n node.nodeName === 'P'\n );\n}"],"names":["xor","props","require$$0","require$$1"],"mappings":"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","x_google_ignoreList":[0,1,2]} |
+23
-20
@@ -1,5 +0,5 @@ | ||
| 'use strict'; | ||
| function getDefaultExportFromCjs (x) { | ||
| return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; | ||
| } | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| /** | ||
@@ -9,3 +9,3 @@ * Expose `xor` | ||
| var componentXor = xor; | ||
| var componentXor = xor$1; | ||
@@ -25,3 +25,3 @@ /** | ||
| function xor(a, b) { | ||
| function xor$1(a, b) { | ||
| return a ^ b; | ||
@@ -46,3 +46,3 @@ } | ||
| var componentProps = function(str, fn){ | ||
| var p = unique(props(str)); | ||
| var p = unique(props$1(str)); | ||
| if (fn && 'string' == typeof fn) fn = prefixed(fn); | ||
@@ -61,3 +61,3 @@ if (fn) return map(str, p, fn); | ||
| function props(str) { | ||
| function props$1(str) { | ||
| return str | ||
@@ -122,6 +122,6 @@ .replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g, '') | ||
| var xor = componentXor; | ||
| var props = componentProps; | ||
| /** | ||
@@ -253,7 +253,7 @@ * Export `Iterator` | ||
| while (node) { | ||
| if (componentXor(next, closing) && node[child]) { | ||
| if (xor(next, closing) && node[child]) { | ||
| // element with children: <em>...</em> | ||
| node = node[child]; | ||
| closing = !next; | ||
| } else if (1 == node.nodeType && !node[child] && componentXor(next, closing)) { | ||
| } else if (1 == node.nodeType && !node[child] && xor(next, closing)) { | ||
| // empty element tag: <em></em> | ||
@@ -387,3 +387,3 @@ closing = next; | ||
| case 'string': | ||
| return new Function('node', 'return ' + componentProps(expr, 'node.')); | ||
| return new Function('node', 'return ' + props(expr, 'node.')); | ||
| case 'function': | ||
@@ -428,2 +428,9 @@ return expr; | ||
| var iterator = /*@__PURE__*/getDefaultExportFromCjs(domIterator); | ||
| /** | ||
| * Module Dependencies | ||
| */ | ||
| var selection = window.getSelection(); | ||
@@ -509,3 +516,3 @@ | ||
| var i = domIterator(el.firstChild, el); | ||
| var i = iterator(el.firstChild, el); | ||
@@ -655,3 +662,3 @@ var next = i.node; | ||
| var i = domIterator(el.firstChild, el); | ||
| var i = iterator(el.firstChild, el); | ||
@@ -761,7 +768,3 @@ var next = i.node; | ||
| exports.applyRange = applyRange; | ||
| exports.getWindowSelection = getWindowSelection; | ||
| exports.isSelected = isSelected; | ||
| exports.setRange = setRange; | ||
| exports.getRange = getRange; | ||
| exports.annotateRange = annotateRange; | ||
| export { annotateRange, applyRange, getRange, getWindowSelection, isSelected, setRange }; | ||
| //# sourceMappingURL=index.js.map |
+32
-29
| { | ||
| "name": "selection-ranges", | ||
| "version": "3.0.3", | ||
| "version": "4.0.0", | ||
| "description": "Selection range manipulation for contenteditable elements", | ||
| "main": "dist/index.js", | ||
| "module": "dist/index.esm.js", | ||
| "type": "module", | ||
| "exports": { | ||
| ".": { | ||
| "import": "./dist/index.js" | ||
| }, | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "scripts": { | ||
| "all": "run-s lint test bundle test:integration", | ||
| "bundle": "rollup -c", | ||
| "all": "run-s lint test", | ||
| "bundle": "rollup -c --bundleConfigAsCjs", | ||
| "dev": "npm test -- --auto-watch --no-single-run", | ||
| "lint": "eslint .", | ||
| "prepublishOnly": "run-s bundle test:integration", | ||
| "test": "karma start karma.conf.js", | ||
| "test:integration": "karma start test/integration/karma.conf.js" | ||
| "pretest": "run-s bundle", | ||
| "test": "karma start karma.conf.cjs", | ||
| "prepare": "run-s bundle" | ||
| }, | ||
@@ -31,28 +36,26 @@ "repository": { | ||
| "devDependencies": { | ||
| "babel-core": "^6.26.3", | ||
| "babel-preset-env": "^1.7.0", | ||
| "babelify": "^8.0.0", | ||
| "browserify": "^16.1.0", | ||
| "chai": "^4.1.2", | ||
| "eslint": "^5.13.0", | ||
| "eslint-plugin-bpmn-io": "^0.6.1", | ||
| "karma": "^4.0.0", | ||
| "karma-browserify": "^5.2.0", | ||
| "@rollup/plugin-commonjs": "^25.0.7", | ||
| "@rollup/plugin-node-resolve": "^15.2.3", | ||
| "@rollup/plugin-terser": "^0.4.4", | ||
| "chai": "^4.4.1", | ||
| "eslint": "^8.57.0", | ||
| "eslint-plugin-bpmn-io": "^1.0.0", | ||
| "karma": "^6.4.3", | ||
| "karma-chai": "^0.1.0", | ||
| "karma-chrome-launcher": "^2.2.0", | ||
| "karma-firefox-launcher": "^1.1.0", | ||
| "karma-mocha": "^1.3.0", | ||
| "karma-phantomjs-launcher": "^1.0.4", | ||
| "mocha": "^5.0.1", | ||
| "karma-chrome-launcher": "^3.2.0", | ||
| "karma-firefox-launcher": "^2.1.3", | ||
| "karma-mocha": "^2.0.1", | ||
| "karma-webpack": "^5.0.1", | ||
| "mocha": "^10.3.0", | ||
| "npm-run-all": "^4.1.2", | ||
| "puppeteer": "^1.1.0", | ||
| "rollup": "^1.1.2", | ||
| "rollup-plugin-commonjs": "^9.1.0", | ||
| "rollup-plugin-node-resolve": "^4.0.0", | ||
| "rollup-plugin-uglify": "^6.0.2", | ||
| "watchify": "^3.10.0" | ||
| "puppeteer": "^22.4.0", | ||
| "rollup": "^4.12.1", | ||
| "webpack": "^5.90.3" | ||
| }, | ||
| "dependencies": { | ||
| "dom-iterator": "^1.0.0" | ||
| } | ||
| }, | ||
| "files": [ | ||
| "dist" | ||
| ] | ||
| } |
+3
-3
| # selection-ranges | ||
| [](https://travis-ci.org/nikku/selection-ranges) | ||
| [](https://github.com/nikku/selection-ranges/actions/workflows/CI.yml) | ||
| Manipulate selection ranges on contenteditable elements. | ||
| Manipulate selection ranges on `contenteditable` elements. | ||
@@ -75,2 +75,2 @@ | ||
| MIT | ||
| MIT |
-63
| # Changelog | ||
| All notable changes to [selection-ranges](https://github.com/nikku/selection-ranges) are documented here. We use [semantic versioning](http://semver.org/) for releases. | ||
| ## Unreleased | ||
| ___Note:__ Yet to be released changes appear here._ | ||
| ## 3.0.3 | ||
| * `CHORE`: package `LICENSE` file | ||
| ## 3.0.2 | ||
| _Republish of `v3.0.1` with update changelog._ | ||
| ## 3.0.1 | ||
| * `FIX`: make `babel` a development dependency ([#1](https://github.com/nikku/selection-ranges/issues/1)) | ||
| ## 3.0.0 | ||
| ### Breaking Changes | ||
| * `FIX`: remove browser field again; it confuses modern module bundlers. This partially reverts `v2.1.0` | ||
| ## 2.1.0 | ||
| * `CHORE`: add `browser` field | ||
| ## 2.0.0 | ||
| * `CHORE`: migrate to ES6 | ||
| * `FEAT`: provide pre-built distribution in dist folder (UMD export name is `SelectionRanges`) | ||
| ## 1.2.3 | ||
| * `FIX`: correctly set range on empty node | ||
| ## 1.2.2 | ||
| * `FIX`: correctly set range post paragraphs (IE 11) | ||
| ## 1.2.1 | ||
| * `FIX`: ensure `isSelected(el)` supports IE 11 | ||
| ## 1.2.0 | ||
| * `FEAT`: support MS Edge style `div` containers | ||
| ## 1.1.0 | ||
| * `FEAT`: add `isSelected(el)` util | ||
| ## 1.0.1 | ||
| * `CHORE`: ignore development assets | ||
| * `CHORE`: add `CHANGELOG.md` | ||
| ## 1.0.0 | ||
| * initial implementation |
| /** | ||
| * Expose `xor` | ||
| */ | ||
| var componentXor = xor; | ||
| /** | ||
| * XOR utility | ||
| * | ||
| * T T F | ||
| * T F T | ||
| * F T T | ||
| * F F F | ||
| * | ||
| * @param {Boolean} a | ||
| * @param {Boolean} b | ||
| * @return {Boolean} | ||
| */ | ||
| function xor(a, b) { | ||
| return a ^ b; | ||
| } | ||
| /** | ||
| * Global Names | ||
| */ | ||
| var globals = /\b(Array|Date|Object|Math|JSON)\b/g; | ||
| /** | ||
| * Return immediate identifiers parsed from `str`. | ||
| * | ||
| * @param {String} str | ||
| * @param {String|Function} map function or prefix | ||
| * @return {Array} | ||
| * @api public | ||
| */ | ||
| var componentProps = function(str, fn){ | ||
| var p = unique(props(str)); | ||
| if (fn && 'string' == typeof fn) fn = prefixed(fn); | ||
| if (fn) return map(str, p, fn); | ||
| return p; | ||
| }; | ||
| /** | ||
| * Return immediate identifiers in `str`. | ||
| * | ||
| * @param {String} str | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function props(str) { | ||
| return str | ||
| .replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g, '') | ||
| .replace(globals, '') | ||
| .match(/[a-zA-Z_]\w*/g) | ||
| || []; | ||
| } | ||
| /** | ||
| * Return `str` with `props` mapped with `fn`. | ||
| * | ||
| * @param {String} str | ||
| * @param {Array} props | ||
| * @param {Function} fn | ||
| * @return {String} | ||
| * @api private | ||
| */ | ||
| function map(str, props, fn) { | ||
| var re = /\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\/|[a-zA-Z_]\w*/g; | ||
| return str.replace(re, function(_){ | ||
| if ('(' == _[_.length - 1]) return fn(_); | ||
| if (!~props.indexOf(_)) return _; | ||
| return fn(_); | ||
| }); | ||
| } | ||
| /** | ||
| * Return unique array. | ||
| * | ||
| * @param {Array} arr | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function unique(arr) { | ||
| var ret = []; | ||
| for (var i = 0; i < arr.length; i++) { | ||
| if (~ret.indexOf(arr[i])) continue; | ||
| ret.push(arr[i]); | ||
| } | ||
| return ret; | ||
| } | ||
| /** | ||
| * Map with prefix `str`. | ||
| */ | ||
| function prefixed(str) { | ||
| return function(_){ | ||
| return str + _; | ||
| }; | ||
| } | ||
| /** | ||
| * Module Dependencies | ||
| */ | ||
| /** | ||
| * Export `Iterator` | ||
| */ | ||
| var domIterator = Iterator; | ||
| /** | ||
| * Initialize `Iterator` | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| function Iterator(node, root) { | ||
| if (!(this instanceof Iterator)) return new Iterator(node, root); | ||
| this.node = this.start = this.peeked = node; | ||
| this.root = root; | ||
| this.closingTag = false; | ||
| this._revisit = true; | ||
| this._selects = []; | ||
| this._rejects = []; | ||
| if (node && this.higher(node)) { | ||
| throw new Error('root must be a parent or ancestor to node'); | ||
| } | ||
| } | ||
| /** | ||
| * Reset the Iterator | ||
| * | ||
| * @param {Node} node (optional) | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reset = function(node) { | ||
| this.node = node || this.start; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Revisit element nodes. Defaults to `true` | ||
| */ | ||
| Iterator.prototype.revisit = function(revisit) { | ||
| this._revisit = undefined == revisit ? true : revisit; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the opening tag | ||
| */ | ||
| Iterator.prototype.opening = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = false; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atOpening = function() { | ||
| return !this.closingTag; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.closing = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = true; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atClosing = function() { | ||
| return this.closingTag; | ||
| }; | ||
| /** | ||
| * Next node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.next = traverse('nextSibling', 'firstChild'); | ||
| /** | ||
| * Previous node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.previous = | ||
| Iterator.prototype.prev = traverse('previousSibling', 'lastChild'); | ||
| /** | ||
| * Make traverse function | ||
| * | ||
| * @param {String} dir | ||
| * @param {String} child | ||
| * @return {Function} | ||
| * @api private | ||
| */ | ||
| function traverse(dir, child) { | ||
| var next = dir == 'nextSibling'; | ||
| return function walk(expr, n, peek) { | ||
| expr = this.compile(expr); | ||
| n = n && n > 0 ? n : 1; | ||
| var node = this.node; | ||
| var closing = this.closingTag; | ||
| var revisit = this._revisit; | ||
| while (node) { | ||
| if (componentXor(next, closing) && node[child]) { | ||
| // element with children: <em>...</em> | ||
| node = node[child]; | ||
| closing = !next; | ||
| } else if (1 == node.nodeType && !node[child] && componentXor(next, closing)) { | ||
| // empty element tag: <em></em> | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } else if (node[dir]) { | ||
| // element has a neighbor: ...<em></em>... | ||
| node = node[dir]; | ||
| closing = !next; | ||
| } else { | ||
| // done with current layer, move up. | ||
| node = node.parentNode; | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } | ||
| if (!node || this.higher(node, this.root)) break; | ||
| if (expr(node) && this.selects(node, peek) && this.rejects(node, peek)) { | ||
| if (--n) continue; | ||
| if (!peek) this.node = node; | ||
| this.closingTag = closing; | ||
| return node; | ||
| } | ||
| } | ||
| return null; | ||
| }; | ||
| } | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be truthy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.select = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._selects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the selects ORing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.selects = function(node, peek) { | ||
| var exprs = this._selects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return true; | ||
| } | ||
| return false; | ||
| }; | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be falsy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reject = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._rejects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the reject expressions ANDing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.rejects = function(node, peek) { | ||
| var exprs = this._rejects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return false; | ||
| } | ||
| return true; | ||
| }; | ||
| /** | ||
| * Check if node is higher | ||
| * than root. | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.higher = function(node) { | ||
| var root = this.root; | ||
| if (!root) return false; | ||
| node = node.parentNode; | ||
| while (node && node != root) node = node.parentNode; | ||
| return node != root; | ||
| }; | ||
| /** | ||
| * Compile an expression | ||
| * | ||
| * @param {String|Function|Number} expr | ||
| * @return {Function} | ||
| */ | ||
| Iterator.prototype.compile = function(expr) { | ||
| switch (typeof expr) { | ||
| case 'number': | ||
| return function(node) { return expr == node.nodeType; }; | ||
| case 'string': | ||
| return new Function('node', 'return ' + componentProps(expr, 'node.')); | ||
| case 'function': | ||
| return expr; | ||
| default: | ||
| return function() { return true; }; | ||
| } | ||
| }; | ||
| /** | ||
| * Peek in either direction | ||
| * `n` nodes. Peek backwards | ||
| * using negative numbers. | ||
| * | ||
| * @param {Number} n (optional) | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.peak = | ||
| Iterator.prototype.peek = function(expr, n) { | ||
| if (arguments.length == 1) n = expr, expr = true; | ||
| n = undefined == n ? 1 : n; | ||
| if (!n) return this.node; | ||
| else if (n > 0) return this.next(expr, n, true); | ||
| else return this.prev(expr, Math.abs(n), true); | ||
| }; | ||
| /** | ||
| * Add a plugin | ||
| * | ||
| * @param {Function} fn | ||
| * @return {Iterator} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.use = function(fn) { | ||
| fn(this); | ||
| return this; | ||
| }; | ||
| var selection = window.getSelection(); | ||
| /** | ||
| * Add selection / insert cursor. | ||
| * | ||
| * @param {Range} range | ||
| */ | ||
| function applyRange(range) { | ||
| selection.removeAllRanges(); | ||
| selection.addRange(range); | ||
| } | ||
| /** | ||
| * Get current document selection. | ||
| * | ||
| * @return {Selection} | ||
| */ | ||
| function getWindowSelection() { | ||
| return selection; | ||
| } | ||
| /** | ||
| * Return true if element is part of window selection. | ||
| * | ||
| * @param {Element} el | ||
| * @return {Boolean} | ||
| */ | ||
| function isSelected(el) { | ||
| if (!selection.rangeCount) { | ||
| return null; | ||
| } | ||
| var focusNode = selection.focusNode; | ||
| // IE supports Node#contains for elements only | ||
| // thus we ensure we check against an actual Element node | ||
| if (isText(focusNode)) { | ||
| focusNode = focusNode.parentNode; | ||
| } | ||
| return el == focusNode || el.contains(focusNode); | ||
| } | ||
| /** | ||
| * Set cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| * @param {SelectionRange} selection | ||
| */ | ||
| function setRange(el, selection) { | ||
| var range = createRange(el, selection); | ||
| applyRange(range); | ||
| } | ||
| /** | ||
| * Get cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| */ | ||
| function getRange(el) { | ||
| if (!isSelected(el)) { | ||
| return null; | ||
| } | ||
| var range = selection.getRangeAt(0); | ||
| var startContainer = range.startContainer; | ||
| var endContainer = range.endContainer; | ||
| var startOffset = range.startOffset; | ||
| var endOffset = range.endOffset; | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var last; | ||
| var isClosing = false; | ||
| var selectionStart; | ||
| var count = 0; | ||
| function isBeforeEnd(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === endContainer && | ||
| referenceNode == endContainer.childNodes[endOffset] | ||
| ); | ||
| } | ||
| function isBeforeStart(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === startContainer && | ||
| referenceNode == startContainer.childNodes[startOffset] | ||
| ); | ||
| } | ||
| while (next) { | ||
| // start before node | ||
| if (isBeforeStart(next)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next)) { | ||
| break; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| last && (last.nextSibling == next) && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| // #text node | ||
| if (startContainer === next) { | ||
| selectionStart = count + startOffset; | ||
| } | ||
| if (endContainer === next) { | ||
| count += endOffset; | ||
| break; | ||
| } | ||
| count += next.textContent.length; | ||
| } | ||
| if (isText(next) || isClosing) { | ||
| // start before node | ||
| if (isBeforeStart(next, next.nextSibling)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next, next.nextSibling)) { | ||
| break; | ||
| } | ||
| } | ||
| last = next; | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // selection until end of text | ||
| return { | ||
| start: typeof selectionStart === 'undefined' ? count : selectionStart, | ||
| end: count | ||
| }; | ||
| } | ||
| /** | ||
| * Annotate the given text with markers based on the | ||
| * given range. | ||
| * | ||
| * @param {String} text | ||
| * @param {SelectionRange} range | ||
| * | ||
| * @return {String} annotated text | ||
| */ | ||
| function annotateRange(text, range) { | ||
| var str; | ||
| if (range.start === range.end) { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '|' + | ||
| text.substring(range.start) | ||
| ); | ||
| } else { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '<' + | ||
| text.substring(range.start, range.end) + | ||
| '>' + | ||
| text.substring(range.end) | ||
| ); | ||
| } | ||
| return str; | ||
| } | ||
| //////// helpers /////////////////////////// | ||
| function createRange(el, selection) { | ||
| var start = selection.start; | ||
| var end = selection.end; | ||
| var range = document.createRange(); | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var isClosing = false; | ||
| var count = 0; | ||
| var length; | ||
| while (next) { | ||
| if (count === start) { | ||
| if (isClosing) { | ||
| range.setStartAfter(next); | ||
| } else { | ||
| range.setStartBefore(next); | ||
| } | ||
| } | ||
| if (count === end) { | ||
| if (isClosing) { | ||
| range.setEndAfter(next); | ||
| } else { | ||
| range.setEndBefore(next); | ||
| } | ||
| return range; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| next.previousSibling && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| length = next.textContent.length; | ||
| if (count <= start && count + length > start) { | ||
| range.setStart(next, start - count); | ||
| } | ||
| if (count + length > end) { | ||
| range.setEnd(next, end - count); | ||
| return range; | ||
| } | ||
| count += length; | ||
| } | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // out of range | ||
| if (count <= start) { | ||
| if (el.lastChild) { | ||
| range.setStartAfter(el.lastChild); | ||
| } else { | ||
| range.setStart(el, 0); | ||
| } | ||
| } | ||
| if (el.lastChild) { | ||
| range.setEndAfter(el.lastChild); | ||
| } else { | ||
| range.setEnd(el, 0); | ||
| } | ||
| return range; | ||
| } | ||
| function isText(node) { | ||
| return node.nodeType === 3; | ||
| } | ||
| function isBr(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'BR' | ||
| ); | ||
| } | ||
| function isDiv(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'DIV' | ||
| ); | ||
| } | ||
| function isParagraph(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'P' | ||
| ); | ||
| } | ||
| export { applyRange, getWindowSelection, isSelected, setRange, getRange, annotateRange }; |
| /** | ||
| * Expose `xor` | ||
| */ | ||
| var componentXor = xor; | ||
| /** | ||
| * XOR utility | ||
| * | ||
| * T T F | ||
| * T F T | ||
| * F T T | ||
| * F F F | ||
| * | ||
| * @param {Boolean} a | ||
| * @param {Boolean} b | ||
| * @return {Boolean} | ||
| */ | ||
| function xor(a, b) { | ||
| return a ^ b; | ||
| } | ||
| /** | ||
| * Global Names | ||
| */ | ||
| var globals = /\b(Array|Date|Object|Math|JSON)\b/g; | ||
| /** | ||
| * Return immediate identifiers parsed from `str`. | ||
| * | ||
| * @param {String} str | ||
| * @param {String|Function} map function or prefix | ||
| * @return {Array} | ||
| * @api public | ||
| */ | ||
| var componentProps = function(str, fn){ | ||
| var p = unique(props(str)); | ||
| if (fn && 'string' == typeof fn) fn = prefixed(fn); | ||
| if (fn) return map(str, p, fn); | ||
| return p; | ||
| }; | ||
| /** | ||
| * Return immediate identifiers in `str`. | ||
| * | ||
| * @param {String} str | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function props(str) { | ||
| return str | ||
| .replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g, '') | ||
| .replace(globals, '') | ||
| .match(/[a-zA-Z_]\w*/g) | ||
| || []; | ||
| } | ||
| /** | ||
| * Return `str` with `props` mapped with `fn`. | ||
| * | ||
| * @param {String} str | ||
| * @param {Array} props | ||
| * @param {Function} fn | ||
| * @return {String} | ||
| * @api private | ||
| */ | ||
| function map(str, props, fn) { | ||
| var re = /\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\/|[a-zA-Z_]\w*/g; | ||
| return str.replace(re, function(_){ | ||
| if ('(' == _[_.length - 1]) return fn(_); | ||
| if (!~props.indexOf(_)) return _; | ||
| return fn(_); | ||
| }); | ||
| } | ||
| /** | ||
| * Return unique array. | ||
| * | ||
| * @param {Array} arr | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function unique(arr) { | ||
| var ret = []; | ||
| for (var i = 0; i < arr.length; i++) { | ||
| if (~ret.indexOf(arr[i])) continue; | ||
| ret.push(arr[i]); | ||
| } | ||
| return ret; | ||
| } | ||
| /** | ||
| * Map with prefix `str`. | ||
| */ | ||
| function prefixed(str) { | ||
| return function(_){ | ||
| return str + _; | ||
| }; | ||
| } | ||
| /** | ||
| * Module Dependencies | ||
| */ | ||
| /** | ||
| * Export `Iterator` | ||
| */ | ||
| var domIterator = Iterator; | ||
| /** | ||
| * Initialize `Iterator` | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| function Iterator(node, root) { | ||
| if (!(this instanceof Iterator)) return new Iterator(node, root); | ||
| this.node = this.start = this.peeked = node; | ||
| this.root = root; | ||
| this.closingTag = false; | ||
| this._revisit = true; | ||
| this._selects = []; | ||
| this._rejects = []; | ||
| if (node && this.higher(node)) { | ||
| throw new Error('root must be a parent or ancestor to node'); | ||
| } | ||
| } | ||
| /** | ||
| * Reset the Iterator | ||
| * | ||
| * @param {Node} node (optional) | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reset = function(node) { | ||
| this.node = node || this.start; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Revisit element nodes. Defaults to `true` | ||
| */ | ||
| Iterator.prototype.revisit = function(revisit) { | ||
| this._revisit = undefined == revisit ? true : revisit; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the opening tag | ||
| */ | ||
| Iterator.prototype.opening = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = false; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atOpening = function() { | ||
| return !this.closingTag; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.closing = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = true; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atClosing = function() { | ||
| return this.closingTag; | ||
| }; | ||
| /** | ||
| * Next node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.next = traverse('nextSibling', 'firstChild'); | ||
| /** | ||
| * Previous node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.previous = | ||
| Iterator.prototype.prev = traverse('previousSibling', 'lastChild'); | ||
| /** | ||
| * Make traverse function | ||
| * | ||
| * @param {String} dir | ||
| * @param {String} child | ||
| * @return {Function} | ||
| * @api private | ||
| */ | ||
| function traverse(dir, child) { | ||
| var next = dir == 'nextSibling'; | ||
| return function walk(expr, n, peek) { | ||
| expr = this.compile(expr); | ||
| n = n && n > 0 ? n : 1; | ||
| var node = this.node; | ||
| var closing = this.closingTag; | ||
| var revisit = this._revisit; | ||
| while (node) { | ||
| if (componentXor(next, closing) && node[child]) { | ||
| // element with children: <em>...</em> | ||
| node = node[child]; | ||
| closing = !next; | ||
| } else if (1 == node.nodeType && !node[child] && componentXor(next, closing)) { | ||
| // empty element tag: <em></em> | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } else if (node[dir]) { | ||
| // element has a neighbor: ...<em></em>... | ||
| node = node[dir]; | ||
| closing = !next; | ||
| } else { | ||
| // done with current layer, move up. | ||
| node = node.parentNode; | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } | ||
| if (!node || this.higher(node, this.root)) break; | ||
| if (expr(node) && this.selects(node, peek) && this.rejects(node, peek)) { | ||
| if (--n) continue; | ||
| if (!peek) this.node = node; | ||
| this.closingTag = closing; | ||
| return node; | ||
| } | ||
| } | ||
| return null; | ||
| }; | ||
| } | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be truthy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.select = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._selects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the selects ORing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.selects = function(node, peek) { | ||
| var exprs = this._selects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return true; | ||
| } | ||
| return false; | ||
| }; | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be falsy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reject = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._rejects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the reject expressions ANDing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.rejects = function(node, peek) { | ||
| var exprs = this._rejects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return false; | ||
| } | ||
| return true; | ||
| }; | ||
| /** | ||
| * Check if node is higher | ||
| * than root. | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.higher = function(node) { | ||
| var root = this.root; | ||
| if (!root) return false; | ||
| node = node.parentNode; | ||
| while (node && node != root) node = node.parentNode; | ||
| return node != root; | ||
| }; | ||
| /** | ||
| * Compile an expression | ||
| * | ||
| * @param {String|Function|Number} expr | ||
| * @return {Function} | ||
| */ | ||
| Iterator.prototype.compile = function(expr) { | ||
| switch (typeof expr) { | ||
| case 'number': | ||
| return function(node) { return expr == node.nodeType; }; | ||
| case 'string': | ||
| return new Function('node', 'return ' + componentProps(expr, 'node.')); | ||
| case 'function': | ||
| return expr; | ||
| default: | ||
| return function() { return true; }; | ||
| } | ||
| }; | ||
| /** | ||
| * Peek in either direction | ||
| * `n` nodes. Peek backwards | ||
| * using negative numbers. | ||
| * | ||
| * @param {Number} n (optional) | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.peak = | ||
| Iterator.prototype.peek = function(expr, n) { | ||
| if (arguments.length == 1) n = expr, expr = true; | ||
| n = undefined == n ? 1 : n; | ||
| if (!n) return this.node; | ||
| else if (n > 0) return this.next(expr, n, true); | ||
| else return this.prev(expr, Math.abs(n), true); | ||
| }; | ||
| /** | ||
| * Add a plugin | ||
| * | ||
| * @param {Function} fn | ||
| * @return {Iterator} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.use = function(fn) { | ||
| fn(this); | ||
| return this; | ||
| }; | ||
| var selection = window.getSelection(); | ||
| /** | ||
| * Add selection / insert cursor. | ||
| * | ||
| * @param {Range} range | ||
| */ | ||
| function applyRange(range) { | ||
| selection.removeAllRanges(); | ||
| selection.addRange(range); | ||
| } | ||
| /** | ||
| * Get current document selection. | ||
| * | ||
| * @return {Selection} | ||
| */ | ||
| function getWindowSelection() { | ||
| return selection; | ||
| } | ||
| /** | ||
| * Return true if element is part of window selection. | ||
| * | ||
| * @param {Element} el | ||
| * @return {Boolean} | ||
| */ | ||
| function isSelected(el) { | ||
| if (!selection.rangeCount) { | ||
| return null; | ||
| } | ||
| var focusNode = selection.focusNode; | ||
| // IE supports Node#contains for elements only | ||
| // thus we ensure we check against an actual Element node | ||
| if (isText(focusNode)) { | ||
| focusNode = focusNode.parentNode; | ||
| } | ||
| return el == focusNode || el.contains(focusNode); | ||
| } | ||
| /** | ||
| * Set cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| * @param {SelectionRange} selection | ||
| */ | ||
| function setRange(el, selection) { | ||
| var range = createRange(el, selection); | ||
| applyRange(range); | ||
| } | ||
| /** | ||
| * Get cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| */ | ||
| function getRange(el) { | ||
| if (!isSelected(el)) { | ||
| return null; | ||
| } | ||
| var range = selection.getRangeAt(0); | ||
| var startContainer = range.startContainer; | ||
| var endContainer = range.endContainer; | ||
| var startOffset = range.startOffset; | ||
| var endOffset = range.endOffset; | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var last; | ||
| var isClosing = false; | ||
| var selectionStart; | ||
| var count = 0; | ||
| function isBeforeEnd(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === endContainer && | ||
| referenceNode == endContainer.childNodes[endOffset] | ||
| ); | ||
| } | ||
| function isBeforeStart(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === startContainer && | ||
| referenceNode == startContainer.childNodes[startOffset] | ||
| ); | ||
| } | ||
| while (next) { | ||
| // start before node | ||
| if (isBeforeStart(next)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next)) { | ||
| break; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| last && (last.nextSibling == next) && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| // #text node | ||
| if (startContainer === next) { | ||
| selectionStart = count + startOffset; | ||
| } | ||
| if (endContainer === next) { | ||
| count += endOffset; | ||
| break; | ||
| } | ||
| count += next.textContent.length; | ||
| } | ||
| if (isText(next) || isClosing) { | ||
| // start before node | ||
| if (isBeforeStart(next, next.nextSibling)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next, next.nextSibling)) { | ||
| break; | ||
| } | ||
| } | ||
| last = next; | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // selection until end of text | ||
| return { | ||
| start: typeof selectionStart === 'undefined' ? count : selectionStart, | ||
| end: count | ||
| }; | ||
| } | ||
| /** | ||
| * Annotate the given text with markers based on the | ||
| * given range. | ||
| * | ||
| * @param {String} text | ||
| * @param {SelectionRange} range | ||
| * | ||
| * @return {String} annotated text | ||
| */ | ||
| function annotateRange(text, range) { | ||
| var str; | ||
| if (range.start === range.end) { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '|' + | ||
| text.substring(range.start) | ||
| ); | ||
| } else { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '<' + | ||
| text.substring(range.start, range.end) + | ||
| '>' + | ||
| text.substring(range.end) | ||
| ); | ||
| } | ||
| return str; | ||
| } | ||
| // helpers /////////////////////////// | ||
| function createRange(el, selection) { | ||
| var start = selection.start; | ||
| var end = selection.end; | ||
| var range = document.createRange(); | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var isClosing = false; | ||
| var count = 0; | ||
| var length; | ||
| while (next) { | ||
| if (count === start) { | ||
| if (isClosing) { | ||
| range.setStartAfter(next); | ||
| } else { | ||
| range.setStartBefore(next); | ||
| } | ||
| } | ||
| if (count === end) { | ||
| if (isClosing) { | ||
| range.setEndAfter(next); | ||
| } else { | ||
| range.setEndBefore(next); | ||
| } | ||
| return range; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| next.previousSibling && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| length = next.textContent.length; | ||
| if (count <= start && count + length > start) { | ||
| range.setStart(next, start - count); | ||
| } | ||
| if (count + length > end) { | ||
| range.setEnd(next, end - count); | ||
| return range; | ||
| } | ||
| count += length; | ||
| } | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // out of range | ||
| if (count <= start) { | ||
| if (el.lastChild) { | ||
| range.setStartAfter(el.lastChild); | ||
| } else { | ||
| range.setStart(el, 0); | ||
| } | ||
| } | ||
| if (el.lastChild) { | ||
| range.setEndAfter(el.lastChild); | ||
| } else { | ||
| range.setEnd(el, 0); | ||
| } | ||
| return range; | ||
| } | ||
| function isText(node) { | ||
| return node.nodeType === 3; | ||
| } | ||
| function isBr(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'BR' | ||
| ); | ||
| } | ||
| function isDiv(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'DIV' | ||
| ); | ||
| } | ||
| function isParagraph(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'P' | ||
| ); | ||
| } | ||
| export { applyRange, getWindowSelection, isSelected, setRange, getRange, annotateRange }; |
| (function (global, factory) { | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
| typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
| (global = global || self, factory(global.SelectionRanges = {})); | ||
| }(this, function (exports) { 'use strict'; | ||
| /** | ||
| * Expose `xor` | ||
| */ | ||
| var componentXor = xor; | ||
| /** | ||
| * XOR utility | ||
| * | ||
| * T T F | ||
| * T F T | ||
| * F T T | ||
| * F F F | ||
| * | ||
| * @param {Boolean} a | ||
| * @param {Boolean} b | ||
| * @return {Boolean} | ||
| */ | ||
| function xor(a, b) { | ||
| return a ^ b; | ||
| } | ||
| /** | ||
| * Global Names | ||
| */ | ||
| var globals = /\b(Array|Date|Object|Math|JSON)\b/g; | ||
| /** | ||
| * Return immediate identifiers parsed from `str`. | ||
| * | ||
| * @param {String} str | ||
| * @param {String|Function} map function or prefix | ||
| * @return {Array} | ||
| * @api public | ||
| */ | ||
| var componentProps = function(str, fn){ | ||
| var p = unique(props(str)); | ||
| if (fn && 'string' == typeof fn) fn = prefixed(fn); | ||
| if (fn) return map(str, p, fn); | ||
| return p; | ||
| }; | ||
| /** | ||
| * Return immediate identifiers in `str`. | ||
| * | ||
| * @param {String} str | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function props(str) { | ||
| return str | ||
| .replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g, '') | ||
| .replace(globals, '') | ||
| .match(/[a-zA-Z_]\w*/g) | ||
| || []; | ||
| } | ||
| /** | ||
| * Return `str` with `props` mapped with `fn`. | ||
| * | ||
| * @param {String} str | ||
| * @param {Array} props | ||
| * @param {Function} fn | ||
| * @return {String} | ||
| * @api private | ||
| */ | ||
| function map(str, props, fn) { | ||
| var re = /\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\/|[a-zA-Z_]\w*/g; | ||
| return str.replace(re, function(_){ | ||
| if ('(' == _[_.length - 1]) return fn(_); | ||
| if (!~props.indexOf(_)) return _; | ||
| return fn(_); | ||
| }); | ||
| } | ||
| /** | ||
| * Return unique array. | ||
| * | ||
| * @param {Array} arr | ||
| * @return {Array} | ||
| * @api private | ||
| */ | ||
| function unique(arr) { | ||
| var ret = []; | ||
| for (var i = 0; i < arr.length; i++) { | ||
| if (~ret.indexOf(arr[i])) continue; | ||
| ret.push(arr[i]); | ||
| } | ||
| return ret; | ||
| } | ||
| /** | ||
| * Map with prefix `str`. | ||
| */ | ||
| function prefixed(str) { | ||
| return function(_){ | ||
| return str + _; | ||
| }; | ||
| } | ||
| /** | ||
| * Module Dependencies | ||
| */ | ||
| /** | ||
| * Export `Iterator` | ||
| */ | ||
| var domIterator = Iterator; | ||
| /** | ||
| * Initialize `Iterator` | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| function Iterator(node, root) { | ||
| if (!(this instanceof Iterator)) return new Iterator(node, root); | ||
| this.node = this.start = this.peeked = node; | ||
| this.root = root; | ||
| this.closingTag = false; | ||
| this._revisit = true; | ||
| this._selects = []; | ||
| this._rejects = []; | ||
| if (node && this.higher(node)) { | ||
| throw new Error('root must be a parent or ancestor to node'); | ||
| } | ||
| } | ||
| /** | ||
| * Reset the Iterator | ||
| * | ||
| * @param {Node} node (optional) | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reset = function(node) { | ||
| this.node = node || this.start; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Revisit element nodes. Defaults to `true` | ||
| */ | ||
| Iterator.prototype.revisit = function(revisit) { | ||
| this._revisit = undefined == revisit ? true : revisit; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the opening tag | ||
| */ | ||
| Iterator.prototype.opening = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = false; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atOpening = function() { | ||
| return !this.closingTag; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.closing = function() { | ||
| if (1 == this.node.nodeType) this.closingTag = true; | ||
| return this; | ||
| }; | ||
| /** | ||
| * Jump to the closing tag | ||
| */ | ||
| Iterator.prototype.atClosing = function() { | ||
| return this.closingTag; | ||
| }; | ||
| /** | ||
| * Next node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.next = traverse('nextSibling', 'firstChild'); | ||
| /** | ||
| * Previous node | ||
| * | ||
| * @param {Number} type | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.previous = | ||
| Iterator.prototype.prev = traverse('previousSibling', 'lastChild'); | ||
| /** | ||
| * Make traverse function | ||
| * | ||
| * @param {String} dir | ||
| * @param {String} child | ||
| * @return {Function} | ||
| * @api private | ||
| */ | ||
| function traverse(dir, child) { | ||
| var next = dir == 'nextSibling'; | ||
| return function walk(expr, n, peek) { | ||
| expr = this.compile(expr); | ||
| n = n && n > 0 ? n : 1; | ||
| var node = this.node; | ||
| var closing = this.closingTag; | ||
| var revisit = this._revisit; | ||
| while (node) { | ||
| if (componentXor(next, closing) && node[child]) { | ||
| // element with children: <em>...</em> | ||
| node = node[child]; | ||
| closing = !next; | ||
| } else if (1 == node.nodeType && !node[child] && componentXor(next, closing)) { | ||
| // empty element tag: <em></em> | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } else if (node[dir]) { | ||
| // element has a neighbor: ...<em></em>... | ||
| node = node[dir]; | ||
| closing = !next; | ||
| } else { | ||
| // done with current layer, move up. | ||
| node = node.parentNode; | ||
| closing = next; | ||
| if (!revisit) continue; | ||
| } | ||
| if (!node || this.higher(node, this.root)) break; | ||
| if (expr(node) && this.selects(node, peek) && this.rejects(node, peek)) { | ||
| if (--n) continue; | ||
| if (!peek) this.node = node; | ||
| this.closingTag = closing; | ||
| return node; | ||
| } | ||
| } | ||
| return null; | ||
| }; | ||
| } | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be truthy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.select = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._selects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the selects ORing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.selects = function(node, peek) { | ||
| var exprs = this._selects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return true; | ||
| } | ||
| return false; | ||
| }; | ||
| /** | ||
| * Select nodes that cause `expr(node)` | ||
| * to be falsy | ||
| * | ||
| * @param {Number|String|Function} expr | ||
| * @return {Iterator} self | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.reject = function(expr) { | ||
| expr = this.compile(expr); | ||
| this._rejects.push(expr); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Run through the reject expressions ANDing each | ||
| * | ||
| * @param {Node} node | ||
| * @param {Boolean} peek | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.rejects = function(node, peek) { | ||
| var exprs = this._rejects; | ||
| var len = exprs.length; | ||
| if (!len) return true; | ||
| for (var i = 0; i < len; i++) { | ||
| if (exprs[i].call(this, node, peek)) return false; | ||
| } | ||
| return true; | ||
| }; | ||
| /** | ||
| * Check if node is higher | ||
| * than root. | ||
| * | ||
| * @param {Node} node | ||
| * @param {Node} root | ||
| * @return {Boolean} | ||
| * @api private | ||
| */ | ||
| Iterator.prototype.higher = function(node) { | ||
| var root = this.root; | ||
| if (!root) return false; | ||
| node = node.parentNode; | ||
| while (node && node != root) node = node.parentNode; | ||
| return node != root; | ||
| }; | ||
| /** | ||
| * Compile an expression | ||
| * | ||
| * @param {String|Function|Number} expr | ||
| * @return {Function} | ||
| */ | ||
| Iterator.prototype.compile = function(expr) { | ||
| switch (typeof expr) { | ||
| case 'number': | ||
| return function(node) { return expr == node.nodeType; }; | ||
| case 'string': | ||
| return new Function('node', 'return ' + componentProps(expr, 'node.')); | ||
| case 'function': | ||
| return expr; | ||
| default: | ||
| return function() { return true; }; | ||
| } | ||
| }; | ||
| /** | ||
| * Peek in either direction | ||
| * `n` nodes. Peek backwards | ||
| * using negative numbers. | ||
| * | ||
| * @param {Number} n (optional) | ||
| * @return {Node|null} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.peak = | ||
| Iterator.prototype.peek = function(expr, n) { | ||
| if (arguments.length == 1) n = expr, expr = true; | ||
| n = undefined == n ? 1 : n; | ||
| if (!n) return this.node; | ||
| else if (n > 0) return this.next(expr, n, true); | ||
| else return this.prev(expr, Math.abs(n), true); | ||
| }; | ||
| /** | ||
| * Add a plugin | ||
| * | ||
| * @param {Function} fn | ||
| * @return {Iterator} | ||
| * @api public | ||
| */ | ||
| Iterator.prototype.use = function(fn) { | ||
| fn(this); | ||
| return this; | ||
| }; | ||
| var selection = window.getSelection(); | ||
| /** | ||
| * Add selection / insert cursor. | ||
| * | ||
| * @param {Range} range | ||
| */ | ||
| function applyRange(range) { | ||
| selection.removeAllRanges(); | ||
| selection.addRange(range); | ||
| } | ||
| /** | ||
| * Get current document selection. | ||
| * | ||
| * @return {Selection} | ||
| */ | ||
| function getWindowSelection() { | ||
| return selection; | ||
| } | ||
| /** | ||
| * Return true if element is part of window selection. | ||
| * | ||
| * @param {Element} el | ||
| * @return {Boolean} | ||
| */ | ||
| function isSelected(el) { | ||
| if (!selection.rangeCount) { | ||
| return null; | ||
| } | ||
| var focusNode = selection.focusNode; | ||
| // IE supports Node#contains for elements only | ||
| // thus we ensure we check against an actual Element node | ||
| if (isText(focusNode)) { | ||
| focusNode = focusNode.parentNode; | ||
| } | ||
| return el == focusNode || el.contains(focusNode); | ||
| } | ||
| /** | ||
| * Set cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| * @param {SelectionRange} selection | ||
| */ | ||
| function setRange(el, selection) { | ||
| var range = createRange(el, selection); | ||
| applyRange(range); | ||
| } | ||
| /** | ||
| * Get cursor or selection position. | ||
| * | ||
| * @param {Element} el | ||
| */ | ||
| function getRange(el) { | ||
| if (!isSelected(el)) { | ||
| return null; | ||
| } | ||
| var range = selection.getRangeAt(0); | ||
| var startContainer = range.startContainer; | ||
| var endContainer = range.endContainer; | ||
| var startOffset = range.startOffset; | ||
| var endOffset = range.endOffset; | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var last; | ||
| var isClosing = false; | ||
| var selectionStart; | ||
| var count = 0; | ||
| function isBeforeEnd(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === endContainer && | ||
| referenceNode == endContainer.childNodes[endOffset] | ||
| ); | ||
| } | ||
| function isBeforeStart(node, referenceNode) { | ||
| if (arguments.length === 1) { | ||
| referenceNode = node; | ||
| } | ||
| return ( | ||
| node.parentNode === startContainer && | ||
| referenceNode == startContainer.childNodes[startOffset] | ||
| ); | ||
| } | ||
| while (next) { | ||
| // start before node | ||
| if (isBeforeStart(next)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next)) { | ||
| break; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| last && (last.nextSibling == next) && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| // #text node | ||
| if (startContainer === next) { | ||
| selectionStart = count + startOffset; | ||
| } | ||
| if (endContainer === next) { | ||
| count += endOffset; | ||
| break; | ||
| } | ||
| count += next.textContent.length; | ||
| } | ||
| if (isText(next) || isClosing) { | ||
| // start before node | ||
| if (isBeforeStart(next, next.nextSibling)) { | ||
| selectionStart = count; | ||
| } | ||
| // end before node | ||
| if (isBeforeEnd(next, next.nextSibling)) { | ||
| break; | ||
| } | ||
| } | ||
| last = next; | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // selection until end of text | ||
| return { | ||
| start: typeof selectionStart === 'undefined' ? count : selectionStart, | ||
| end: count | ||
| }; | ||
| } | ||
| /** | ||
| * Annotate the given text with markers based on the | ||
| * given range. | ||
| * | ||
| * @param {String} text | ||
| * @param {SelectionRange} range | ||
| * | ||
| * @return {String} annotated text | ||
| */ | ||
| function annotateRange(text, range) { | ||
| var str; | ||
| if (range.start === range.end) { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '|' + | ||
| text.substring(range.start) | ||
| ); | ||
| } else { | ||
| str = ( | ||
| text.substring(0, range.start) + | ||
| '<' + | ||
| text.substring(range.start, range.end) + | ||
| '>' + | ||
| text.substring(range.end) | ||
| ); | ||
| } | ||
| return str; | ||
| } | ||
| // helpers /////////////////////////// | ||
| function createRange(el, selection) { | ||
| var start = selection.start; | ||
| var end = selection.end; | ||
| var range = document.createRange(); | ||
| var i = domIterator(el.firstChild, el); | ||
| var next = i.node; | ||
| var isClosing = false; | ||
| var count = 0; | ||
| var length; | ||
| while (next) { | ||
| if (count === start) { | ||
| if (isClosing) { | ||
| range.setStartAfter(next); | ||
| } else { | ||
| range.setStartBefore(next); | ||
| } | ||
| } | ||
| if (count === end) { | ||
| if (isClosing) { | ||
| range.setEndAfter(next); | ||
| } else { | ||
| range.setEndBefore(next); | ||
| } | ||
| return range; | ||
| } | ||
| if (!isClosing) { | ||
| if ( | ||
| isBr(next) || ( | ||
| next.previousSibling && ( | ||
| isDiv(next) || | ||
| isParagraph(next) | ||
| ) | ||
| ) | ||
| ) { | ||
| count++; | ||
| } | ||
| } | ||
| if (isText(next)) { | ||
| length = next.textContent.length; | ||
| if (count <= start && count + length > start) { | ||
| range.setStart(next, start - count); | ||
| } | ||
| if (count + length > end) { | ||
| range.setEnd(next, end - count); | ||
| return range; | ||
| } | ||
| count += length; | ||
| } | ||
| next = i.next(); | ||
| isClosing = i.closingTag; | ||
| } | ||
| // out of range | ||
| if (count <= start) { | ||
| if (el.lastChild) { | ||
| range.setStartAfter(el.lastChild); | ||
| } else { | ||
| range.setStart(el, 0); | ||
| } | ||
| } | ||
| if (el.lastChild) { | ||
| range.setEndAfter(el.lastChild); | ||
| } else { | ||
| range.setEnd(el, 0); | ||
| } | ||
| return range; | ||
| } | ||
| function isText(node) { | ||
| return node.nodeType === 3; | ||
| } | ||
| function isBr(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'BR' | ||
| ); | ||
| } | ||
| function isDiv(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'DIV' | ||
| ); | ||
| } | ||
| function isParagraph(node) { | ||
| return ( | ||
| node.nodeType === 1 && | ||
| node.nodeName === 'P' | ||
| ); | ||
| } | ||
| exports.applyRange = applyRange; | ||
| exports.getWindowSelection = getWindowSelection; | ||
| exports.isSelected = isSelected; | ||
| exports.setRange = setRange; | ||
| exports.getRange = getRange; | ||
| exports.annotateRange = annotateRange; | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| })); |
| !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).SelectionRanges={})}(this,function(t){"use strict";var f=function(t,e){return t^e};var s=/\b(Array|Date|Object|Math|JSON)\b/g,n=function(t,e){var n,r,i,o=function(t){for(var e=[],n=0;n<t.length;n++)~e.indexOf(t[n])||e.push(t[n]);return e}(t.replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g,"").replace(s,"").match(/[a-zA-Z_]\w*/g)||[]);return e&&"string"==typeof e&&(n=e,e=function(t){return n+t}),e?(r=o,i=e,t.replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\/|[a-zA-Z_]\w*/g,function(t){return"("==t[t.length-1]?i(t):~r.indexOf(t)?i(t):t})):o};var d=r;function r(t,e){if(!(this instanceof r))return new r(t,e);if(this.node=this.start=this.peeked=t,this.root=e,this.closingTag=!1,this._revisit=!0,this._selects=[],this._rejects=[],t&&this.higher(t))throw new Error("root must be a parent or ancestor to node")}function e(s,u){var a="nextSibling"==s;return function(t,e,n){t=this.compile(t),e=e&&0<e?e:1;for(var r=this.node,i=this.closingTag,o=this._revisit;r;){if(f(a,i)&&r[u])r=r[u],i=!a;else if(1==r.nodeType&&!r[u]&&f(a,i)){if(i=a,!o)continue}else if(r[s])r=r[s],i=!a;else if(r=r.parentNode,i=a,!o)continue;if(!r||this.higher(r,this.root))break;if(t(r)&&this.selects(r,n)&&this.rejects(r,n)){if(--e)continue;return n||(this.node=r),this.closingTag=i,r}}return null}}r.prototype.reset=function(t){return this.node=t||this.start,this},r.prototype.revisit=function(t){return this._revisit=null==t||t,this},r.prototype.opening=function(){return 1==this.node.nodeType&&(this.closingTag=!1),this},r.prototype.atOpening=function(){return!this.closingTag},r.prototype.closing=function(){return 1==this.node.nodeType&&(this.closingTag=!0),this},r.prototype.atClosing=function(){return this.closingTag},r.prototype.next=e("nextSibling","firstChild"),r.prototype.previous=r.prototype.prev=e("previousSibling","lastChild"),r.prototype.select=function(t){return t=this.compile(t),this._selects.push(t),this},r.prototype.selects=function(t,e){var n=this._selects,r=n.length;if(!r)return!0;for(var i=0;i<r;i++)if(n[i].call(this,t,e))return!0;return!1},r.prototype.reject=function(t){return t=this.compile(t),this._rejects.push(t),this},r.prototype.rejects=function(t,e){var n=this._rejects,r=n.length;if(!r)return!0;for(var i=0;i<r;i++)if(n[i].call(this,t,e))return!1;return!0},r.prototype.higher=function(t){var e=this.root;if(!e)return!1;for(t=t.parentNode;t&&t!=e;)t=t.parentNode;return t!=e},r.prototype.compile=function(e){switch(typeof e){case"number":return function(t){return e==t.nodeType};case"string":return new Function("node","return "+n(e,"node."));case"function":return e;default:return function(){return!0}}},r.prototype.peak=r.prototype.peek=function(t,e){return 1==arguments.length&&(e=t,t=!0),(e=null==e?1:e)?0<e?this.next(t,e,!0):this.prev(t,Math.abs(e),!0):this.node},r.prototype.use=function(t){return t(this),this};var g=window.getSelection();function i(t){g.removeAllRanges(),g.addRange(t)}function y(t){if(!g.rangeCount)return null;var e=g.focusNode;return v(e)&&(e=e.parentNode),t==e||t.contains(e)}function v(t){return 3===t.nodeType}function b(t){return 1===t.nodeType&&"BR"===t.nodeName}function S(t){return 1===t.nodeType&&"DIV"===t.nodeName}function T(t){return 1===t.nodeType&&"P"===t.nodeName}t.applyRange=i,t.getWindowSelection=function(){return g},t.isSelected=y,t.setRange=function(t,e){i(function(t,e){for(var n,r=e.start,i=e.end,o=document.createRange(),s=d(t.firstChild,t),u=s.node,a=!1,f=0;u;){if(f===r&&(a?o.setStartAfter(u):o.setStartBefore(u)),f===i)return a?o.setEndAfter(u):o.setEndBefore(u),o;if(a||(b(u)||u.previousSibling&&(S(u)||T(u)))&&f++,v(u)){if(n=u.textContent.length,f<=r&&r<f+n&&o.setStart(u,r-f),i<f+n)return o.setEnd(u,i-f),o;f+=n}u=s.next(),a=s.closingTag}return f<=r&&(t.lastChild?o.setStartAfter(t.lastChild):o.setStart(t,0)),t.lastChild?o.setEndAfter(t.lastChild):o.setEnd(t,0),o}(t,e))},t.getRange=function(t){if(!y(t))return null;var e,n,r=g.getRangeAt(0),i=r.startContainer,o=r.endContainer,s=r.startOffset,u=r.endOffset,a=d(t.firstChild,t),f=a.node,c=!1,l=0;function h(t,e){return 1===arguments.length&&(e=t),t.parentNode===o&&e==o.childNodes[u]}function p(t,e){return 1===arguments.length&&(e=t),t.parentNode===i&&e==i.childNodes[s]}for(;f&&(p(f)&&(n=l),!h(f));){if(c||(b(f)||e&&e.nextSibling==f&&(S(f)||T(f)))&&l++,v(f)){if(i===f&&(n=l+s),o===f){l+=u;break}l+=f.textContent.length}if((v(f)||c)&&(p(f,f.nextSibling)&&(n=l),h(f,f.nextSibling)))break;e=f,f=a.next(),c=a.closingTag}return{start:void 0===n?l:n,end:l}},t.annotateRange=function(t,e){return e.start===e.end?t.substring(0,e.start)+"|"+t.substring(e.start):t.substring(0,e.start)+"<"+t.substring(e.start,e.end)+">"+t.substring(e.end)},Object.defineProperty(t,"__esModule",{value:!0})}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
17
-22.73%1
-50%76
1.33%2
-60%Yes
NaN47152
-27.51%5
-44.44%610
-74.97%