index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _helperPluginUtils = require("@babel/helper-plugin-utils");
  7. var _core = require("@babel/core");
  8. var _default = (0, _helperPluginUtils.declare)(api => {
  9. api.assertVersion(7);
  10. const surrogate = /[\ud800-\udfff]/g;
  11. const unicodeEscape = /(\\+)u\{([0-9a-fA-F]+)\}/g;
  12. function escape(code) {
  13. let str = code.toString(16);
  14. while (str.length < 4) str = "0" + str;
  15. return "\\u" + str;
  16. }
  17. function replacer(match, backslashes, code) {
  18. if (backslashes.length % 2 === 0) {
  19. return match;
  20. }
  21. const char = String.fromCodePoint(parseInt(code, 16));
  22. const escaped = backslashes.slice(0, -1) + escape(char.charCodeAt(0));
  23. return char.length === 1 ? escaped : escaped + escape(char.charCodeAt(1));
  24. }
  25. function replaceUnicodeEscapes(str) {
  26. return str.replace(unicodeEscape, replacer);
  27. }
  28. function getUnicodeEscape(str) {
  29. let match;
  30. while (match = unicodeEscape.exec(str)) {
  31. if (match[1].length % 2 === 0) continue;
  32. unicodeEscape.lastIndex = 0;
  33. return match[0];
  34. }
  35. return null;
  36. }
  37. return {
  38. name: "transform-unicode-escapes",
  39. manipulateOptions({
  40. generatorOpts
  41. }) {
  42. var _generatorOpts$jsescO, _generatorOpts$jsescO2;
  43. if (!generatorOpts.jsescOption) {
  44. generatorOpts.jsescOption = {};
  45. }
  46. (_generatorOpts$jsescO2 = (_generatorOpts$jsescO = generatorOpts.jsescOption).minimal) != null ? _generatorOpts$jsescO2 : _generatorOpts$jsescO.minimal = false;
  47. },
  48. visitor: {
  49. Identifier(path) {
  50. const {
  51. node,
  52. key
  53. } = path;
  54. const {
  55. name
  56. } = node;
  57. const replaced = name.replace(surrogate, c => {
  58. return `_u${c.charCodeAt(0).toString(16)}`;
  59. });
  60. if (name === replaced) return;
  61. const str = _core.types.inherits(_core.types.stringLiteral(name), node);
  62. if (key === "key") {
  63. path.replaceWith(str);
  64. return;
  65. }
  66. const {
  67. parentPath,
  68. scope
  69. } = path;
  70. if (parentPath.isMemberExpression({
  71. property: node
  72. }) || parentPath.isOptionalMemberExpression({
  73. property: node
  74. })) {
  75. parentPath.node.computed = true;
  76. path.replaceWith(str);
  77. return;
  78. }
  79. const binding = scope.getBinding(name);
  80. if (binding) {
  81. scope.rename(name, scope.generateUid(replaced));
  82. return;
  83. }
  84. throw path.buildCodeFrameError(`Can't reference '${name}' as a bare identifier`);
  85. },
  86. "StringLiteral|DirectiveLiteral"(path) {
  87. const {
  88. node
  89. } = path;
  90. const {
  91. extra
  92. } = node;
  93. if (extra != null && extra.raw) extra.raw = replaceUnicodeEscapes(extra.raw);
  94. },
  95. TemplateElement(path) {
  96. const {
  97. node,
  98. parentPath
  99. } = path;
  100. const {
  101. value
  102. } = node;
  103. const firstEscape = getUnicodeEscape(value.raw);
  104. if (!firstEscape) return;
  105. const grandParent = parentPath.parentPath;
  106. if (grandParent.isTaggedTemplateExpression()) {
  107. throw path.buildCodeFrameError(`Can't replace Unicode escape '${firstEscape}' inside tagged template literals. You can enable '@babel/plugin-transform-template-literals' to compile them to classic strings.`);
  108. }
  109. value.raw = replaceUnicodeEscapes(value.raw);
  110. }
  111. }
  112. };
  113. });
  114. exports.default = _default;