/** * The MIT License (MIT) * Copyright (c) 2017-present Dmitry Soshnikov */ 'use strict'; var UPPER_A_CP = 'A'.codePointAt(0); var UPPER_Z_CP = 'Z'.codePointAt(0); var LOWER_A_CP = 'a'.codePointAt(0); var LOWER_Z_CP = 'z'.codePointAt(0); var DIGIT_0_CP = '0'.codePointAt(0); var DIGIT_9_CP = '9'.codePointAt(0); /** * A regexp-tree plugin to transform coded chars into simple chars. * * \u0061 -> a */ module.exports = { Char: function Char(path) { var node = path.node, parent = path.parent; if (isNaN(node.codePoint) || node.kind === 'simple') { return; } if (parent.type === 'ClassRange') { if (!isSimpleRange(parent)) { return; } } if (!isPrintableASCIIChar(node.codePoint)) { return; } var symbol = String.fromCodePoint(node.codePoint); var newChar = { type: 'Char', kind: 'simple', value: symbol, symbol: symbol, codePoint: node.codePoint }; if (needsEscape(symbol, parent.type)) { newChar.escaped = true; } path.replace(newChar); } }; /** * Checks if a range is included either in 0-9, a-z or A-Z * @param classRange * @returns {boolean} */ function isSimpleRange(classRange) { var from = classRange.from, to = classRange.to; return from.codePoint >= DIGIT_0_CP && from.codePoint <= DIGIT_9_CP && to.codePoint >= DIGIT_0_CP && to.codePoint <= DIGIT_9_CP || from.codePoint >= UPPER_A_CP && from.codePoint <= UPPER_Z_CP && to.codePoint >= UPPER_A_CP && to.codePoint <= UPPER_Z_CP || from.codePoint >= LOWER_A_CP && from.codePoint <= LOWER_Z_CP && to.codePoint >= LOWER_A_CP && to.codePoint <= LOWER_Z_CP; } /** * Checks if a code point in the range of printable ASCII chars * (DEL char excluded) * @param codePoint * @returns {boolean} */ function isPrintableASCIIChar(codePoint) { return codePoint >= 0x20 && codePoint <= 0x7e; } function needsEscape(symbol, parentType) { if (parentType === 'ClassRange' || parentType === 'CharacterClass') { return (/[\]\\^-]/.test(symbol) ); } return (/[*[()+?^$./\\|{}]/.test(symbol) ); }