123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- 'use strict';
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.Formats = undefined;
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
- var _escapeStringRegexp = require('escape-string-regexp');
- var _escapeStringRegexp2 = _interopRequireDefault(_escapeStringRegexp);
- var _formats = require('./formats');
- var _formats2 = _interopRequireDefault(_formats);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- /**
- * TextareaEditor class.
- *
- * @param {HTMLElement} el - the textarea element to wrap around
- */
- var TextareaEditor = function () {
- function TextareaEditor(el) {
- _classCallCheck(this, TextareaEditor);
- this.el = el;
- }
- /**
- * Set or get selection range.
- *
- * @param {Array} [range]
- * @return {Array|TextareaEditor}
- */
- _createClass(TextareaEditor, [{
- key: 'range',
- value: function range(_range) {
- var el = this.el;
- if (_range == null) {
- return [el.selectionStart || 0, el.selectionEnd || 0];
- }
- this.focus();
- var _range2 = _slicedToArray(_range, 2);
- el.selectionStart = _range2[0];
- el.selectionEnd = _range2[1];
- return this;
- }
- /**
- * Insert given text at the current cursor position.
- *
- * @param {String} text - text to insert
- * @return {TextareaEditor}
- */
- }, {
- key: 'insert',
- value: function insert(text) {
- var inserted = true;
- this.el.contentEditable = true;
- this.focus();
- try {
- document.execCommand('insertText', false, text);
- } catch (e) {
- inserted = false;
- }
- this.el.contentEditable = false;
- if (inserted) return this;
- try {
- document.execCommand('ms-beginUndoUnit');
- } catch (e) {}
- var _selection = this.selection(),
- before = _selection.before,
- after = _selection.after;
- this.el.value = before + text + after;
- try {
- document.execCommand('ms-endUndoUnit');
- } catch (e) {}
- var event = document.createEvent('Event');
- event.initEvent('input', true, true);
- this.el.dispatchEvent(event);
- return this;
- }
- /**
- * Set foucs on the TextareaEditor's element.
- *
- * @return {TextareaEditor}
- */
- }, {
- key: 'focus',
- value: function focus() {
- if (document.activeElement !== this.el) this.el.focus();
- return this;
- }
- /**
- * Get selected text.
- *
- * @return {Object}
- * @private
- */
- }, {
- key: 'selection',
- value: function selection() {
- var _range3 = this.range(),
- _range4 = _slicedToArray(_range3, 2),
- start = _range4[0],
- end = _range4[1];
- var value = normalizeNewlines(this.el.value);
- return {
- before: value.slice(0, start),
- content: value.slice(start, end),
- after: value.slice(end)
- };
- }
- /**
- * Get format by name.
- *
- * @param {String|Object} format
- * @return {Object}
- * @private
- */
- }, {
- key: 'getFormat',
- value: function getFormat(format) {
- if ((typeof format === 'undefined' ? 'undefined' : _typeof(format)) == 'object') {
- return normalizeFormat(format);
- }
- if (!_formats2.default.hasOwnProperty(format)) {
- throw new Error('Invalid format ' + format);
- }
- return normalizeFormat(_formats2.default[format]);
- }
- /**
- * Toggle given `format` on current selection.
- * Any additional arguments are passed on to `.format()`.
- *
- * @param {String|Object} format - name of format or an object
- * @return {TextareaEditor}
- */
- }, {
- key: 'toggle',
- value: function toggle(format) {
- if (this.hasFormat(format)) return this.unformat(format);
- for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- args[_key - 1] = arguments[_key];
- }
- return this.format.apply(this, [format].concat(args));
- }
- /**
- * Format current selcetion with given `format`.
- *
- * @param {String|Object} name - name of format or an object
- * @return {TextareaEditor}
- */
- }, {
- key: 'format',
- value: function format(name) {
- for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
- args[_key2 - 1] = arguments[_key2];
- }
- var format = this.getFormat(name);
- var prefix = format.prefix,
- suffix = format.suffix,
- multiline = format.multiline;
- var _selection2 = this.selection(),
- before = _selection2.before,
- content = _selection2.content,
- after = _selection2.after;
- var lines = multiline ? content.split('\n') : [content];
- var _range5 = this.range(),
- _range6 = _slicedToArray(_range5, 2),
- start = _range6[0],
- end = _range6[1];
- // format lines
- lines = lines.map(function (line, i) {
- var pval = maybeCall.apply(undefined, [prefix.value, line, i + 1].concat(args));
- var sval = maybeCall.apply(undefined, [suffix.value, line, i + 1].concat(args));
- if (!multiline || !content.length) {
- start += pval.length;
- end += pval.length;
- } else {
- end += pval.length + sval.length;
- }
- return pval + line + sval;
- });
- var insert = lines.join('\n');
- // newlines before and after block
- if (format.block) {
- var nlb = matchLength(before, /\n+$/);
- var nla = matchLength(after, /^\n+/);
- if (before) {
- while (nlb < 2) {
- insert = '\n' + insert;
- start++;
- end++;
- nlb++;
- }
- }
- if (after) {
- while (nla < 2) {
- insert = insert + '\n';
- nla++;
- }
- }
- }
- this.insert(insert);
- this.range([start, end]);
- return this;
- }
- /**
- * Remove given `format` from current selection.
- *
- * @param {String|Object} name - name of format or an object
- * @return {TextareaEditor}
- */
- }, {
- key: 'unformat',
- value: function unformat(name) {
- if (!this.hasFormat(name)) return this;
- var format = this.getFormat(name);
- var prefix = format.prefix,
- suffix = format.suffix,
- multiline = format.multiline;
- var _selection3 = this.selection(),
- before = _selection3.before,
- content = _selection3.content,
- after = _selection3.after;
- var lines = multiline ? content.split('\n') : [content];
- var _range7 = this.range(),
- _range8 = _slicedToArray(_range7, 2),
- start = _range8[0],
- end = _range8[1];
- // If this is not a multiline format, include prefixes and suffixes just
- // outside the selection.
- if ((!multiline || lines.length == 1) && hasSuffix(before, prefix) && hasPrefix(after, suffix)) {
- start -= suffixLength(before, prefix);
- end += prefixLength(after, suffix);
- this.range([start, end]);
- lines = [this.selection().content];
- }
- // remove formatting from lines
- lines = lines.map(function (line) {
- var plen = prefixLength(line, prefix);
- var slen = suffixLength(line, suffix);
- return line.slice(plen, line.length - slen);
- });
- // insert and set selection
- var insert = lines.join('\n');
- this.insert(insert);
- this.range([start, start + insert.length]);
- return this;
- }
- /**
- * Check if current seletion has given format.
- *
- * @param {String|Object} name - name of format or an object
- * @return {Boolean}
- */
- }, {
- key: 'hasFormat',
- value: function hasFormat(name) {
- var format = this.getFormat(name);
- var prefix = format.prefix,
- suffix = format.suffix,
- multiline = format.multiline;
- var _selection4 = this.selection(),
- before = _selection4.before,
- content = _selection4.content,
- after = _selection4.after;
- var lines = content.split('\n');
- // prefix and suffix outside selection
- if (!multiline || lines.length == 1) {
- return hasSuffix(before, prefix) && hasPrefix(after, suffix) || hasPrefix(content, prefix) && hasSuffix(content, suffix);
- }
- // check which line(s) are formatted
- var formatted = lines.filter(function (line) {
- return hasPrefix(line, prefix) && hasSuffix(line, suffix);
- });
- return formatted.length === lines.length;
- }
- }]);
- return TextareaEditor;
- }();
- // Expose formats
- exports.default = TextareaEditor;
- exports.Formats = _formats2.default;
- /**
- * Check if given prefix is present.
- * @private
- */
- function hasPrefix(text, prefix) {
- var exp = new RegExp('^' + prefix.pattern);
- var result = exp.test(text);
- if (prefix.antipattern) {
- var _exp = new RegExp('^' + prefix.antipattern);
- result = result && !_exp.test(text);
- }
- return result;
- }
- /**
- * Check if given suffix is present.
- * @private
- */
- function hasSuffix(text, suffix) {
- var exp = new RegExp(suffix.pattern + '$');
- var result = exp.test(text);
- if (suffix.antipattern) {
- var _exp2 = new RegExp(suffix.antipattern + '$');
- result = result && !_exp2.test(text);
- }
- return result;
- }
- /**
- * Get length of match.
- * @private
- */
- function matchLength(text, exp) {
- var match = text.match(exp);
- return match ? match[0].length : 0;
- }
- /**
- * Get prefix length.
- * @private
- */
- function prefixLength(text, prefix) {
- var exp = new RegExp('^' + prefix.pattern);
- return matchLength(text, exp);
- }
- /**
- * Get suffix length.
- * @private
- */
- function suffixLength(text, suffix) {
- var exp = new RegExp(suffix.pattern + '$');
- return matchLength(text, exp);
- }
- /**
- * Normalize newlines.
- * @private
- */
- function normalizeNewlines(str) {
- return str.replace('\r\n', '\n');
- }
- /**
- * Normalize format.
- * @private
- */
- function normalizeFormat(format) {
- var clone = Object.assign({}, format);
- clone.prefix = normalizePrefixSuffix(format.prefix);
- clone.suffix = normalizePrefixSuffix(format.suffix);
- return clone;
- }
- /**
- * Normalize prefixes and suffixes.
- * @private
- */
- function normalizePrefixSuffix() {
- var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
- if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object') return value;
- return {
- value: value,
- pattern: (0, _escapeStringRegexp2.default)(value)
- };
- }
- /**
- * Call if function.
- * @private
- */
- function maybeCall(value) {
- for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
- args[_key3 - 1] = arguments[_key3];
- }
- return typeof value == 'function' ? value.apply(undefined, args) : value;
- }
|