UNPKG

electron-text-substitutions

Version:

Substitute text in an input field based on OS X System Preferences

140 lines (118 loc) 7.97 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ellipsis = exports.emDash = exports.closingDoubleQuote = exports.openingDoubleQuote = exports.closingSingleQuote = exports.openingSingleQuote = undefined; 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"); } }; }(); exports.getSubstitutionRegExp = getSubstitutionRegExp; exports.getSmartQuotesRegExp = getSmartQuotesRegExp; exports.getSmartDashesRegExp = getSmartDashesRegExp; exports.scrubInputString = scrubInputString; exports.formatReplacement = formatReplacement; exports.regExpReplacer = regExpReplacer; exports.regExpReviver = regExpReviver; var _lodash = require('lodash'); var openingSingleQuote = exports.openingSingleQuote = '\u2018'; // ‘ var closingSingleQuote = exports.closingSingleQuote = '\u2019'; // ’ var openingDoubleQuote = exports.openingDoubleQuote = '\u201C'; // “ var closingDoubleQuote = exports.closingDoubleQuote = '\u201D'; // ” var emDash = exports.emDash = '\u2014'; // — var ellipsis = exports.ellipsis = '\u2026'; // … /** * Recreate something like \b; we don't want to use \b because no Unicode support. */ var wordBoundary = /[ \n\r\t.,:;|{}()<>'"`+!?«»“”‘’‹›—–−-]/; var startsWithWordBoundary = new RegExp('^' + wordBoundary.source); var endsWithWordBoundary = new RegExp(wordBoundary.source + '$'); /** * @typedef {Object} ReplacementItem * @property {String} match The text to replace * @property {RegExp} regExp A regular expression that matches the text to replace * @property {String} replacement The replacement text */ /** * Creates a regular expression that will match a word and its boundaries– that * is, some surrounding whitespace or separator character. * * @param {String} match The string to match * @return {ReplacementItem} A replacement item; contains a `RegExp` and its replacement */ function getSubstitutionRegExp(match, replacement) { // Require the start of input or a word boundary, unless the string to match // already starts with a boundary (e.g., `(tm)`) in which case we want to // match text like `BigCompany(tm)`. var startOfInputOrBoundary = startsWithWordBoundary.test(match) ? '' : '^|' + wordBoundary.source; // Require a terminating word boundary, unless the string to match already // ends with a boundary (e.g., `<br>`) in which case we will also accept word // characters, to match something like `<br>content`. var wordCharacterOrBoundary = endsWithWordBoundary.test(match) ? '\\w|' + wordBoundary.source : wordBoundary.source; // Capture the left and right boundaries as groups $1 and $2, to align with // `formatReplacement`. Be sure to escape special characters in the string // to match. var regExp = new RegExp('(' + startOfInputOrBoundary + ')' + ('' + (0, _lodash.escapeRegExp)(match)) + ('(' + wordCharacterOrBoundary + ')'), 'u'); return { match: match, regExp: regExp, replacement: replacement }; } /** * Returns an array of regular expressions that will progressively replace * straight quotes with curly quotes. * * @return {Array<ReplacementItem>} An array of replacement items */ function getSmartQuotesRegExp() { return [{ regExp: /((?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))"((?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: closingDoubleQuote }, { regExp: /()"((?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: openingDoubleQuote }, { regExp: /((?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))'((?:[\0-/:-@\[-\^`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: closingSingleQuote }, { regExp: /((?:[\0-/:-@\[-\^`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])|^)'([\t-\r 0-9A-Z_a-z\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])/, replacement: openingSingleQuote }, { regExp: /([0-9A-Z_a-z])'([0-9A-Z_a-z]+(?:[\0-/:-@\[-\^`\{-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: closingSingleQuote }]; } /** * Returns an array of regular expressions that will replace hypens with * em-dashes (and ellipsis, as a bonus). * * @return {Array<ReplacementItem>} An array of replacement items */ function getSmartDashesRegExp() { return [{ regExp: /(^|(?:[\0-,\.-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))\-\-\-((?:[\0-,\.-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: emDash }, { regExp: /(^|(?:[\0-,\.-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))\-\-((?:[\0-,\.-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: emDash }, { regExp: /(^|(?:[\0-\-/-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))\.\.\.((?:[\0-\-/-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/, replacement: ellipsis }]; } /** * Replaces text in an input string using the given replacement items. * * @param {String} input The input string * @param {Array<ReplacementItem>} items An array of replacement items * @return {String} The output string */ function scrubInputString(input, items) { return (0, _lodash.reduce)(items, function (output, _ref) { var regExp = _ref.regExp, replacement = _ref.replacement; return output.replace(regExp, '$1' + replacement + '$2'); }, input); } /** * Preserves whitespace around the match. These expressions match the text * being substituted along with boundaries on the left ($1) and right ($2). */ function formatReplacement(match, replacement) { var _match = _slicedToArray(match, 3), left = _match[1], right = _match[2]; return '' + left + replacement + right; } /** * Can be used as the replacer parameter in `JSON.stringify` to serialize * replacement items. */ function regExpReplacer(key, value) { if (value instanceof RegExp) return value.toString(); return value; } /** * Can be used as the reviver parameter in `JSON.parse` to deserialize * replacement items. */ function regExpReviver(key, value) { if (key === 'regExp') { var _value$match = value.match(/\/(.*)\/(.*)?/), _value$match2 = _slicedToArray(_value$match, 3), regExp = _value$match2[1], flags = _value$match2[2]; return new RegExp(regExp, flags || ''); } return value; }