char-class-to-single-char-transform.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * The MIT License (MIT)
  3. * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
  4. */
  5. 'use strict';
  6. /**
  7. * A regexp-tree plugin to replace single char character classes with
  8. * just that character.
  9. *
  10. * [\d] -> \d, [^\w] -> \W
  11. */
  12. module.exports = {
  13. CharacterClass: function CharacterClass(path) {
  14. var node = path.node;
  15. if (node.expressions.length !== 1 || !isAppropriateChar(node.expressions[0])) {
  16. return;
  17. }
  18. var _node$expressions$ = node.expressions[0],
  19. value = _node$expressions$.value,
  20. kind = _node$expressions$.kind,
  21. escaped = _node$expressions$.escaped;
  22. if (node.negative) {
  23. // For negative can extract only meta chars like [^\w] -> \W
  24. // cannot do for [^a] -> a (wrong).
  25. if (!isMeta(value)) {
  26. return;
  27. }
  28. value = getInverseMeta(value);
  29. }
  30. path.replace({
  31. type: 'Char',
  32. value: value,
  33. kind: kind,
  34. escaped: escaped || shouldEscape(value)
  35. });
  36. }
  37. };
  38. function isAppropriateChar(node) {
  39. return node.type === 'Char' &&
  40. // We don't extract [\b] (backspace) since \b has different
  41. // semantics (word boundary).
  42. node.value !== '\\b';
  43. }
  44. function isMeta(value) {
  45. return (/^\\[dwsDWS]$/.test(value)
  46. );
  47. }
  48. function getInverseMeta(value) {
  49. return (/[dws]/.test(value) ? value.toUpperCase() : value.toLowerCase()
  50. );
  51. }
  52. // Note: \{ and \} are always preserved to avoid `a[{]2[}]` turning
  53. // into `a{2}`.
  54. function shouldEscape(value) {
  55. return (/[*[()+?$./{}|]/.test(value)
  56. );
  57. }