escape-case.js 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. 'use strict';
  2. const {replaceTemplateElement} = require('./fix/index.js');
  3. const MESSAGE_ID = 'escape-case';
  4. const messages = {
  5. [MESSAGE_ID]: 'Use uppercase characters for the value of the escape sequence.',
  6. };
  7. const escapeWithLowercase = /(?<=(?:^|[^\\])(?:\\\\)*\\)(?<data>x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|u{[\dA-Fa-f]+})/g;
  8. const escapePatternWithLowercase = /(?<=(?:^|[^\\])(?:\\\\)*\\)(?<data>x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|u{[\dA-Fa-f]+}|c[a-z])/g;
  9. const getProblem = ({node, original, regex = escapeWithLowercase, fix}) => {
  10. const fixed = original.replace(regex, data => data.slice(0, 1) + data.slice(1).toUpperCase());
  11. if (fixed !== original) {
  12. return {
  13. node,
  14. messageId: MESSAGE_ID,
  15. fix: fixer => fix ? fix(fixer, fixed) : fixer.replaceText(node, fixed),
  16. };
  17. }
  18. };
  19. /** @param {import('eslint').Rule.RuleContext} context */
  20. const create = () => ({
  21. Literal(node) {
  22. if (typeof node.value !== 'string') {
  23. return;
  24. }
  25. return getProblem({
  26. node,
  27. original: node.raw,
  28. });
  29. },
  30. 'Literal[regex]'(node) {
  31. return getProblem({
  32. node,
  33. original: node.raw,
  34. regex: escapePatternWithLowercase,
  35. });
  36. },
  37. TemplateElement(node) {
  38. return getProblem({
  39. node,
  40. original: node.value.raw,
  41. fix: (fixer, fixed) => replaceTemplateElement(fixer, node, fixed),
  42. });
  43. },
  44. });
  45. /** @type {import('eslint').Rule.RuleModule} */
  46. module.exports = {
  47. create,
  48. meta: {
  49. type: 'suggestion',
  50. docs: {
  51. description: 'Require escape sequences to use uppercase values.',
  52. },
  53. fixable: 'code',
  54. messages,
  55. },
  56. };