message-resolver.esm-bundler.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*!
  2. * @intlify/message-resolver v9.1.9
  3. * (c) 2021 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. /**
  7. * Original Utilities
  8. * written by kazuya kawaguchi
  9. */
  10. if ((process.env.NODE_ENV !== 'production')) ;
  11. const hasOwnProperty = Object.prototype.hasOwnProperty;
  12. function hasOwn(obj, key) {
  13. return hasOwnProperty.call(obj, key);
  14. }
  15. const isObject = (val) => // eslint-disable-line
  16. val !== null && typeof val === 'object';
  17. const pathStateMachine = [];
  18. pathStateMachine[0 /* BEFORE_PATH */] = {
  19. ["w" /* WORKSPACE */]: [0 /* BEFORE_PATH */],
  20. ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
  21. ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */],
  22. ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */]
  23. };
  24. pathStateMachine[1 /* IN_PATH */] = {
  25. ["w" /* WORKSPACE */]: [1 /* IN_PATH */],
  26. ["." /* DOT */]: [2 /* BEFORE_IDENT */],
  27. ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */],
  28. ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */]
  29. };
  30. pathStateMachine[2 /* BEFORE_IDENT */] = {
  31. ["w" /* WORKSPACE */]: [2 /* BEFORE_IDENT */],
  32. ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
  33. ["0" /* ZERO */]: [3 /* IN_IDENT */, 0 /* APPEND */]
  34. };
  35. pathStateMachine[3 /* IN_IDENT */] = {
  36. ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
  37. ["0" /* ZERO */]: [3 /* IN_IDENT */, 0 /* APPEND */],
  38. ["w" /* WORKSPACE */]: [1 /* IN_PATH */, 1 /* PUSH */],
  39. ["." /* DOT */]: [2 /* BEFORE_IDENT */, 1 /* PUSH */],
  40. ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */, 1 /* PUSH */],
  41. ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */, 1 /* PUSH */]
  42. };
  43. pathStateMachine[4 /* IN_SUB_PATH */] = {
  44. ["'" /* SINGLE_QUOTE */]: [5 /* IN_SINGLE_QUOTE */, 0 /* APPEND */],
  45. ["\"" /* DOUBLE_QUOTE */]: [6 /* IN_DOUBLE_QUOTE */, 0 /* APPEND */],
  46. ["[" /* LEFT_BRACKET */]: [
  47. 4 /* IN_SUB_PATH */,
  48. 2 /* INC_SUB_PATH_DEPTH */
  49. ],
  50. ["]" /* RIGHT_BRACKET */]: [1 /* IN_PATH */, 3 /* PUSH_SUB_PATH */],
  51. ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
  52. ["l" /* ELSE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */]
  53. };
  54. pathStateMachine[5 /* IN_SINGLE_QUOTE */] = {
  55. ["'" /* SINGLE_QUOTE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */],
  56. ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
  57. ["l" /* ELSE */]: [5 /* IN_SINGLE_QUOTE */, 0 /* APPEND */]
  58. };
  59. pathStateMachine[6 /* IN_DOUBLE_QUOTE */] = {
  60. ["\"" /* DOUBLE_QUOTE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */],
  61. ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
  62. ["l" /* ELSE */]: [6 /* IN_DOUBLE_QUOTE */, 0 /* APPEND */]
  63. };
  64. /**
  65. * Check if an expression is a literal value.
  66. */
  67. const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
  68. function isLiteral(exp) {
  69. return literalValueRE.test(exp);
  70. }
  71. /**
  72. * Strip quotes from a string
  73. */
  74. function stripQuotes(str) {
  75. const a = str.charCodeAt(0);
  76. const b = str.charCodeAt(str.length - 1);
  77. return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
  78. }
  79. /**
  80. * Determine the type of a character in a keypath.
  81. */
  82. function getPathCharType(ch) {
  83. if (ch === undefined || ch === null) {
  84. return "o" /* END_OF_FAIL */;
  85. }
  86. const code = ch.charCodeAt(0);
  87. switch (code) {
  88. case 0x5b: // [
  89. case 0x5d: // ]
  90. case 0x2e: // .
  91. case 0x22: // "
  92. case 0x27: // '
  93. return ch;
  94. case 0x5f: // _
  95. case 0x24: // $
  96. case 0x2d: // -
  97. return "i" /* IDENT */;
  98. case 0x09: // Tab (HT)
  99. case 0x0a: // Newline (LF)
  100. case 0x0d: // Return (CR)
  101. case 0xa0: // No-break space (NBSP)
  102. case 0xfeff: // Byte Order Mark (BOM)
  103. case 0x2028: // Line Separator (LS)
  104. case 0x2029: // Paragraph Separator (PS)
  105. return "w" /* WORKSPACE */;
  106. }
  107. return "i" /* IDENT */;
  108. }
  109. /**
  110. * Format a subPath, return its plain form if it is
  111. * a literal string or number. Otherwise prepend the
  112. * dynamic indicator (*).
  113. */
  114. function formatSubPath(path) {
  115. const trimmed = path.trim();
  116. // invalid leading 0
  117. if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
  118. return false;
  119. }
  120. return isLiteral(trimmed)
  121. ? stripQuotes(trimmed)
  122. : "*" /* ASTARISK */ + trimmed;
  123. }
  124. /**
  125. * Parse a string path into an array of segments
  126. */
  127. function parse(path) {
  128. const keys = [];
  129. let index = -1;
  130. let mode = 0 /* BEFORE_PATH */;
  131. let subPathDepth = 0;
  132. let c;
  133. let key; // eslint-disable-line
  134. let newChar;
  135. let type;
  136. let transition;
  137. let action;
  138. let typeMap;
  139. const actions = [];
  140. actions[0 /* APPEND */] = () => {
  141. if (key === undefined) {
  142. key = newChar;
  143. }
  144. else {
  145. key += newChar;
  146. }
  147. };
  148. actions[1 /* PUSH */] = () => {
  149. if (key !== undefined) {
  150. keys.push(key);
  151. key = undefined;
  152. }
  153. };
  154. actions[2 /* INC_SUB_PATH_DEPTH */] = () => {
  155. actions[0 /* APPEND */]();
  156. subPathDepth++;
  157. };
  158. actions[3 /* PUSH_SUB_PATH */] = () => {
  159. if (subPathDepth > 0) {
  160. subPathDepth--;
  161. mode = 4 /* IN_SUB_PATH */;
  162. actions[0 /* APPEND */]();
  163. }
  164. else {
  165. subPathDepth = 0;
  166. if (key === undefined) {
  167. return false;
  168. }
  169. key = formatSubPath(key);
  170. if (key === false) {
  171. return false;
  172. }
  173. else {
  174. actions[1 /* PUSH */]();
  175. }
  176. }
  177. };
  178. function maybeUnescapeQuote() {
  179. const nextChar = path[index + 1];
  180. if ((mode === 5 /* IN_SINGLE_QUOTE */ &&
  181. nextChar === "'" /* SINGLE_QUOTE */) ||
  182. (mode === 6 /* IN_DOUBLE_QUOTE */ &&
  183. nextChar === "\"" /* DOUBLE_QUOTE */)) {
  184. index++;
  185. newChar = '\\' + nextChar;
  186. actions[0 /* APPEND */]();
  187. return true;
  188. }
  189. }
  190. while (mode !== null) {
  191. index++;
  192. c = path[index];
  193. if (c === '\\' && maybeUnescapeQuote()) {
  194. continue;
  195. }
  196. type = getPathCharType(c);
  197. typeMap = pathStateMachine[mode];
  198. transition = typeMap[type] || typeMap["l" /* ELSE */] || 8 /* ERROR */;
  199. // check parse error
  200. if (transition === 8 /* ERROR */) {
  201. return;
  202. }
  203. mode = transition[0];
  204. if (transition[1] !== undefined) {
  205. action = actions[transition[1]];
  206. if (action) {
  207. newChar = c;
  208. if (action() === false) {
  209. return;
  210. }
  211. }
  212. }
  213. // check parse finish
  214. if (mode === 7 /* AFTER_PATH */) {
  215. return keys;
  216. }
  217. }
  218. }
  219. // path token cache
  220. const cache = new Map();
  221. function resolveValue(obj, path) {
  222. // check object
  223. if (!isObject(obj)) {
  224. return null;
  225. }
  226. // parse path
  227. let hit = cache.get(path);
  228. if (!hit) {
  229. hit = parse(path);
  230. if (hit) {
  231. cache.set(path, hit);
  232. }
  233. }
  234. // check hit
  235. if (!hit) {
  236. return null;
  237. }
  238. // resolve path value
  239. const len = hit.length;
  240. let last = obj;
  241. let i = 0;
  242. while (i < len) {
  243. const val = last[hit[i]];
  244. if (val === undefined) {
  245. return null;
  246. }
  247. last = val;
  248. i++;
  249. }
  250. return last;
  251. }
  252. /**
  253. * Transform flat json in obj to normal json in obj
  254. */
  255. function handleFlatJson(obj) {
  256. // check obj
  257. if (!isObject(obj)) {
  258. return obj;
  259. }
  260. for (const key in obj) {
  261. // check key
  262. if (!hasOwn(obj, key)) {
  263. continue;
  264. }
  265. // handle for normal json
  266. if (!key.includes("." /* DOT */)) {
  267. // recursive process value if value is also a object
  268. if (isObject(obj[key])) {
  269. handleFlatJson(obj[key]);
  270. }
  271. }
  272. // handle for flat json, transform to normal json
  273. else {
  274. // go to the last object
  275. const subKeys = key.split("." /* DOT */);
  276. const lastIndex = subKeys.length - 1;
  277. let currentObj = obj;
  278. for (let i = 0; i < lastIndex; i++) {
  279. if (!(subKeys[i] in currentObj)) {
  280. currentObj[subKeys[i]] = {};
  281. }
  282. currentObj = currentObj[subKeys[i]];
  283. }
  284. // update last object value, delete old property
  285. currentObj[subKeys[lastIndex]] = obj[key];
  286. delete obj[key];
  287. // recursive process value if value is also a object
  288. if (isObject(currentObj[subKeys[lastIndex]])) {
  289. handleFlatJson(currentObj[subKeys[lastIndex]]);
  290. }
  291. }
  292. }
  293. return obj;
  294. }
  295. export { handleFlatJson, parse, resolveValue };