message-compiler.cjs.prod.js 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. /*!
  2. * @intlify/message-compiler v9.1.9
  3. * (c) 2021 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. 'use strict';
  7. Object.defineProperty(exports, '__esModule', { value: true });
  8. var shared = require('@intlify/shared');
  9. var sourceMap = require('source-map');
  10. /** @internal */
  11. const errorMessages = {
  12. // tokenizer error messages
  13. [0 /* EXPECTED_TOKEN */]: `Expected token: '{0}'`,
  14. [1 /* INVALID_TOKEN_IN_PLACEHOLDER */]: `Invalid token in placeholder: '{0}'`,
  15. [2 /* UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER */]: `Unterminated single quote in placeholder`,
  16. [3 /* UNKNOWN_ESCAPE_SEQUENCE */]: `Unknown escape sequence: \\{0}`,
  17. [4 /* INVALID_UNICODE_ESCAPE_SEQUENCE */]: `Invalid unicode escape sequence: {0}`,
  18. [5 /* UNBALANCED_CLOSING_BRACE */]: `Unbalanced closing brace`,
  19. [6 /* UNTERMINATED_CLOSING_BRACE */]: `Unterminated closing brace`,
  20. [7 /* EMPTY_PLACEHOLDER */]: `Empty placeholder`,
  21. [8 /* NOT_ALLOW_NEST_PLACEHOLDER */]: `Not allowed nest placeholder`,
  22. [9 /* INVALID_LINKED_FORMAT */]: `Invalid linked format`,
  23. // parser error messages
  24. [10 /* MUST_HAVE_MESSAGES_IN_PLURAL */]: `Plural must have messages`,
  25. [11 /* UNEXPECTED_EMPTY_LINKED_MODIFIER */]: `Unexpected empty linked modifier`,
  26. [12 /* UNEXPECTED_EMPTY_LINKED_KEY */]: `Unexpected empty linked key`,
  27. [13 /* UNEXPECTED_LEXICAL_ANALYSIS */]: `Unexpected lexical analysis in token: '{0}'`
  28. };
  29. function createCompileError(code, loc, options = {}) {
  30. const { domain, messages, args } = options;
  31. const msg = code;
  32. const error = new SyntaxError(String(msg));
  33. error.code = code;
  34. if (loc) {
  35. error.location = loc;
  36. }
  37. error.domain = domain;
  38. return error;
  39. }
  40. /** @internal */
  41. function defaultOnError(error) {
  42. throw error;
  43. }
  44. const LocationStub = {
  45. start: { line: 1, column: 1, offset: 0 },
  46. end: { line: 1, column: 1, offset: 0 }
  47. };
  48. function createPosition(line, column, offset) {
  49. return { line, column, offset };
  50. }
  51. function createLocation(start, end, source) {
  52. const loc = { start, end };
  53. if (source != null) {
  54. loc.source = source;
  55. }
  56. return loc;
  57. }
  58. const CHAR_SP = ' ';
  59. const CHAR_CR = '\r';
  60. const CHAR_LF = '\n';
  61. const CHAR_LS = String.fromCharCode(0x2028);
  62. const CHAR_PS = String.fromCharCode(0x2029);
  63. function createScanner(str) {
  64. const _buf = str;
  65. let _index = 0;
  66. let _line = 1;
  67. let _column = 1;
  68. let _peekOffset = 0;
  69. const isCRLF = (index) => _buf[index] === CHAR_CR && _buf[index + 1] === CHAR_LF;
  70. const isLF = (index) => _buf[index] === CHAR_LF;
  71. const isPS = (index) => _buf[index] === CHAR_PS;
  72. const isLS = (index) => _buf[index] === CHAR_LS;
  73. const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
  74. const index = () => _index;
  75. const line = () => _line;
  76. const column = () => _column;
  77. const peekOffset = () => _peekOffset;
  78. const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
  79. const currentChar = () => charAt(_index);
  80. const currentPeek = () => charAt(_index + _peekOffset);
  81. function next() {
  82. _peekOffset = 0;
  83. if (isLineEnd(_index)) {
  84. _line++;
  85. _column = 0;
  86. }
  87. if (isCRLF(_index)) {
  88. _index++;
  89. }
  90. _index++;
  91. _column++;
  92. return _buf[_index];
  93. }
  94. function peek() {
  95. if (isCRLF(_index + _peekOffset)) {
  96. _peekOffset++;
  97. }
  98. _peekOffset++;
  99. return _buf[_index + _peekOffset];
  100. }
  101. function reset() {
  102. _index = 0;
  103. _line = 1;
  104. _column = 1;
  105. _peekOffset = 0;
  106. }
  107. function resetPeek(offset = 0) {
  108. _peekOffset = offset;
  109. }
  110. function skipToPeek() {
  111. const target = _index + _peekOffset;
  112. // eslint-disable-next-line no-unmodified-loop-condition
  113. while (target !== _index) {
  114. next();
  115. }
  116. _peekOffset = 0;
  117. }
  118. return {
  119. index,
  120. line,
  121. column,
  122. peekOffset,
  123. charAt,
  124. currentChar,
  125. currentPeek,
  126. next,
  127. peek,
  128. reset,
  129. resetPeek,
  130. skipToPeek
  131. };
  132. }
  133. const EOF = undefined;
  134. const LITERAL_DELIMITER = "'";
  135. const ERROR_DOMAIN$1 = 'tokenizer';
  136. function createTokenizer(source, options = {}) {
  137. const location = options.location !== false;
  138. const _scnr = createScanner(source);
  139. const currentOffset = () => _scnr.index();
  140. const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
  141. const _initLoc = currentPosition();
  142. const _initOffset = currentOffset();
  143. const _context = {
  144. currentType: 14 /* EOF */,
  145. offset: _initOffset,
  146. startLoc: _initLoc,
  147. endLoc: _initLoc,
  148. lastType: 14 /* EOF */,
  149. lastOffset: _initOffset,
  150. lastStartLoc: _initLoc,
  151. lastEndLoc: _initLoc,
  152. braceNest: 0,
  153. inLinked: false,
  154. text: ''
  155. };
  156. const context = () => _context;
  157. const { onError } = options;
  158. function emitError(code, pos, offset, ...args) {
  159. const ctx = context();
  160. pos.column += offset;
  161. pos.offset += offset;
  162. if (onError) {
  163. const loc = createLocation(ctx.startLoc, pos);
  164. const err = createCompileError(code, loc, {
  165. domain: ERROR_DOMAIN$1,
  166. args
  167. });
  168. onError(err);
  169. }
  170. }
  171. function getToken(context, type, value) {
  172. context.endLoc = currentPosition();
  173. context.currentType = type;
  174. const token = { type };
  175. if (location) {
  176. token.loc = createLocation(context.startLoc, context.endLoc);
  177. }
  178. if (value != null) {
  179. token.value = value;
  180. }
  181. return token;
  182. }
  183. const getEndToken = (context) => getToken(context, 14 /* EOF */);
  184. function eat(scnr, ch) {
  185. if (scnr.currentChar() === ch) {
  186. scnr.next();
  187. return ch;
  188. }
  189. else {
  190. emitError(0 /* EXPECTED_TOKEN */, currentPosition(), 0, ch);
  191. return '';
  192. }
  193. }
  194. function peekSpaces(scnr) {
  195. let buf = '';
  196. while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
  197. buf += scnr.currentPeek();
  198. scnr.peek();
  199. }
  200. return buf;
  201. }
  202. function skipSpaces(scnr) {
  203. const buf = peekSpaces(scnr);
  204. scnr.skipToPeek();
  205. return buf;
  206. }
  207. function isIdentifierStart(ch) {
  208. if (ch === EOF) {
  209. return false;
  210. }
  211. const cc = ch.charCodeAt(0);
  212. return ((cc >= 97 && cc <= 122) || // a-z
  213. (cc >= 65 && cc <= 90) || // A-Z
  214. cc === 95 // _
  215. );
  216. }
  217. function isNumberStart(ch) {
  218. if (ch === EOF) {
  219. return false;
  220. }
  221. const cc = ch.charCodeAt(0);
  222. return cc >= 48 && cc <= 57; // 0-9
  223. }
  224. function isNamedIdentifierStart(scnr, context) {
  225. const { currentType } = context;
  226. if (currentType !== 2 /* BraceLeft */) {
  227. return false;
  228. }
  229. peekSpaces(scnr);
  230. const ret = isIdentifierStart(scnr.currentPeek());
  231. scnr.resetPeek();
  232. return ret;
  233. }
  234. function isListIdentifierStart(scnr, context) {
  235. const { currentType } = context;
  236. if (currentType !== 2 /* BraceLeft */) {
  237. return false;
  238. }
  239. peekSpaces(scnr);
  240. const ch = scnr.currentPeek() === '-' ? scnr.peek() : scnr.currentPeek();
  241. const ret = isNumberStart(ch);
  242. scnr.resetPeek();
  243. return ret;
  244. }
  245. function isLiteralStart(scnr, context) {
  246. const { currentType } = context;
  247. if (currentType !== 2 /* BraceLeft */) {
  248. return false;
  249. }
  250. peekSpaces(scnr);
  251. const ret = scnr.currentPeek() === LITERAL_DELIMITER;
  252. scnr.resetPeek();
  253. return ret;
  254. }
  255. function isLinkedDotStart(scnr, context) {
  256. const { currentType } = context;
  257. if (currentType !== 8 /* LinkedAlias */) {
  258. return false;
  259. }
  260. peekSpaces(scnr);
  261. const ret = scnr.currentPeek() === "." /* LinkedDot */;
  262. scnr.resetPeek();
  263. return ret;
  264. }
  265. function isLinkedModifierStart(scnr, context) {
  266. const { currentType } = context;
  267. if (currentType !== 9 /* LinkedDot */) {
  268. return false;
  269. }
  270. peekSpaces(scnr);
  271. const ret = isIdentifierStart(scnr.currentPeek());
  272. scnr.resetPeek();
  273. return ret;
  274. }
  275. function isLinkedDelimiterStart(scnr, context) {
  276. const { currentType } = context;
  277. if (!(currentType === 8 /* LinkedAlias */ ||
  278. currentType === 12 /* LinkedModifier */)) {
  279. return false;
  280. }
  281. peekSpaces(scnr);
  282. const ret = scnr.currentPeek() === ":" /* LinkedDelimiter */;
  283. scnr.resetPeek();
  284. return ret;
  285. }
  286. function isLinkedReferStart(scnr, context) {
  287. const { currentType } = context;
  288. if (currentType !== 10 /* LinkedDelimiter */) {
  289. return false;
  290. }
  291. const fn = () => {
  292. const ch = scnr.currentPeek();
  293. if (ch === "{" /* BraceLeft */) {
  294. return isIdentifierStart(scnr.peek());
  295. }
  296. else if (ch === "@" /* LinkedAlias */ ||
  297. ch === "%" /* Modulo */ ||
  298. ch === "|" /* Pipe */ ||
  299. ch === ":" /* LinkedDelimiter */ ||
  300. ch === "." /* LinkedDot */ ||
  301. ch === CHAR_SP ||
  302. !ch) {
  303. return false;
  304. }
  305. else if (ch === CHAR_LF) {
  306. scnr.peek();
  307. return fn();
  308. }
  309. else {
  310. // other characters
  311. return isIdentifierStart(ch);
  312. }
  313. };
  314. const ret = fn();
  315. scnr.resetPeek();
  316. return ret;
  317. }
  318. function isPluralStart(scnr) {
  319. peekSpaces(scnr);
  320. const ret = scnr.currentPeek() === "|" /* Pipe */;
  321. scnr.resetPeek();
  322. return ret;
  323. }
  324. function isTextStart(scnr, reset = true) {
  325. const fn = (hasSpace = false, prev = '', detectModulo = false) => {
  326. const ch = scnr.currentPeek();
  327. if (ch === "{" /* BraceLeft */) {
  328. return prev === "%" /* Modulo */ ? false : hasSpace;
  329. }
  330. else if (ch === "@" /* LinkedAlias */ || !ch) {
  331. return prev === "%" /* Modulo */ ? true : hasSpace;
  332. }
  333. else if (ch === "%" /* Modulo */) {
  334. scnr.peek();
  335. return fn(hasSpace, "%" /* Modulo */, true);
  336. }
  337. else if (ch === "|" /* Pipe */) {
  338. return prev === "%" /* Modulo */ || detectModulo
  339. ? true
  340. : !(prev === CHAR_SP || prev === CHAR_LF);
  341. }
  342. else if (ch === CHAR_SP) {
  343. scnr.peek();
  344. return fn(true, CHAR_SP, detectModulo);
  345. }
  346. else if (ch === CHAR_LF) {
  347. scnr.peek();
  348. return fn(true, CHAR_LF, detectModulo);
  349. }
  350. else {
  351. return true;
  352. }
  353. };
  354. const ret = fn();
  355. reset && scnr.resetPeek();
  356. return ret;
  357. }
  358. function takeChar(scnr, fn) {
  359. const ch = scnr.currentChar();
  360. if (ch === EOF) {
  361. return EOF;
  362. }
  363. if (fn(ch)) {
  364. scnr.next();
  365. return ch;
  366. }
  367. return null;
  368. }
  369. function takeIdentifierChar(scnr) {
  370. const closure = (ch) => {
  371. const cc = ch.charCodeAt(0);
  372. return ((cc >= 97 && cc <= 122) || // a-z
  373. (cc >= 65 && cc <= 90) || // A-Z
  374. (cc >= 48 && cc <= 57) || // 0-9
  375. cc === 95 || // _
  376. cc === 36 // $
  377. );
  378. };
  379. return takeChar(scnr, closure);
  380. }
  381. function takeDigit(scnr) {
  382. const closure = (ch) => {
  383. const cc = ch.charCodeAt(0);
  384. return cc >= 48 && cc <= 57; // 0-9
  385. };
  386. return takeChar(scnr, closure);
  387. }
  388. function takeHexDigit(scnr) {
  389. const closure = (ch) => {
  390. const cc = ch.charCodeAt(0);
  391. return ((cc >= 48 && cc <= 57) || // 0-9
  392. (cc >= 65 && cc <= 70) || // A-F
  393. (cc >= 97 && cc <= 102)); // a-f
  394. };
  395. return takeChar(scnr, closure);
  396. }
  397. function getDigits(scnr) {
  398. let ch = '';
  399. let num = '';
  400. while ((ch = takeDigit(scnr))) {
  401. num += ch;
  402. }
  403. return num;
  404. }
  405. function readText(scnr) {
  406. let buf = '';
  407. while (true) {
  408. const ch = scnr.currentChar();
  409. if (ch === "{" /* BraceLeft */ ||
  410. ch === "}" /* BraceRight */ ||
  411. ch === "@" /* LinkedAlias */ ||
  412. ch === "|" /* Pipe */ ||
  413. !ch) {
  414. break;
  415. }
  416. else if (ch === "%" /* Modulo */) {
  417. if (isTextStart(scnr)) {
  418. buf += ch;
  419. scnr.next();
  420. }
  421. else {
  422. break;
  423. }
  424. }
  425. else if (ch === CHAR_SP || ch === CHAR_LF) {
  426. if (isTextStart(scnr)) {
  427. buf += ch;
  428. scnr.next();
  429. }
  430. else if (isPluralStart(scnr)) {
  431. break;
  432. }
  433. else {
  434. buf += ch;
  435. scnr.next();
  436. }
  437. }
  438. else {
  439. buf += ch;
  440. scnr.next();
  441. }
  442. }
  443. return buf;
  444. }
  445. function readNamedIdentifier(scnr) {
  446. skipSpaces(scnr);
  447. let ch = '';
  448. let name = '';
  449. while ((ch = takeIdentifierChar(scnr))) {
  450. name += ch;
  451. }
  452. if (scnr.currentChar() === EOF) {
  453. emitError(6 /* UNTERMINATED_CLOSING_BRACE */, currentPosition(), 0);
  454. }
  455. return name;
  456. }
  457. function readListIdentifier(scnr) {
  458. skipSpaces(scnr);
  459. let value = '';
  460. if (scnr.currentChar() === '-') {
  461. scnr.next();
  462. value += `-${getDigits(scnr)}`;
  463. }
  464. else {
  465. value += getDigits(scnr);
  466. }
  467. if (scnr.currentChar() === EOF) {
  468. emitError(6 /* UNTERMINATED_CLOSING_BRACE */, currentPosition(), 0);
  469. }
  470. return value;
  471. }
  472. function readLiteral(scnr) {
  473. skipSpaces(scnr);
  474. eat(scnr, `\'`);
  475. let ch = '';
  476. let literal = '';
  477. const fn = (x) => x !== LITERAL_DELIMITER && x !== CHAR_LF;
  478. while ((ch = takeChar(scnr, fn))) {
  479. if (ch === '\\') {
  480. literal += readEscapeSequence(scnr);
  481. }
  482. else {
  483. literal += ch;
  484. }
  485. }
  486. const current = scnr.currentChar();
  487. if (current === CHAR_LF || current === EOF) {
  488. emitError(2 /* UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER */, currentPosition(), 0);
  489. // TODO: Is it correct really?
  490. if (current === CHAR_LF) {
  491. scnr.next();
  492. eat(scnr, `\'`);
  493. }
  494. return literal;
  495. }
  496. eat(scnr, `\'`);
  497. return literal;
  498. }
  499. function readEscapeSequence(scnr) {
  500. const ch = scnr.currentChar();
  501. switch (ch) {
  502. case '\\':
  503. case `\'`:
  504. scnr.next();
  505. return `\\${ch}`;
  506. case 'u':
  507. return readUnicodeEscapeSequence(scnr, ch, 4);
  508. case 'U':
  509. return readUnicodeEscapeSequence(scnr, ch, 6);
  510. default:
  511. emitError(3 /* UNKNOWN_ESCAPE_SEQUENCE */, currentPosition(), 0, ch);
  512. return '';
  513. }
  514. }
  515. function readUnicodeEscapeSequence(scnr, unicode, digits) {
  516. eat(scnr, unicode);
  517. let sequence = '';
  518. for (let i = 0; i < digits; i++) {
  519. const ch = takeHexDigit(scnr);
  520. if (!ch) {
  521. emitError(4 /* INVALID_UNICODE_ESCAPE_SEQUENCE */, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
  522. break;
  523. }
  524. sequence += ch;
  525. }
  526. return `\\${unicode}${sequence}`;
  527. }
  528. function readInvalidIdentifier(scnr) {
  529. skipSpaces(scnr);
  530. let ch = '';
  531. let identifiers = '';
  532. const closure = (ch) => ch !== "{" /* BraceLeft */ &&
  533. ch !== "}" /* BraceRight */ &&
  534. ch !== CHAR_SP &&
  535. ch !== CHAR_LF;
  536. while ((ch = takeChar(scnr, closure))) {
  537. identifiers += ch;
  538. }
  539. return identifiers;
  540. }
  541. function readLinkedModifier(scnr) {
  542. let ch = '';
  543. let name = '';
  544. while ((ch = takeIdentifierChar(scnr))) {
  545. name += ch;
  546. }
  547. return name;
  548. }
  549. function readLinkedRefer(scnr) {
  550. const fn = (detect = false, buf) => {
  551. const ch = scnr.currentChar();
  552. if (ch === "{" /* BraceLeft */ ||
  553. ch === "%" /* Modulo */ ||
  554. ch === "@" /* LinkedAlias */ ||
  555. ch === "|" /* Pipe */ ||
  556. !ch) {
  557. return buf;
  558. }
  559. else if (ch === CHAR_SP) {
  560. return buf;
  561. }
  562. else if (ch === CHAR_LF) {
  563. buf += ch;
  564. scnr.next();
  565. return fn(detect, buf);
  566. }
  567. else {
  568. buf += ch;
  569. scnr.next();
  570. return fn(true, buf);
  571. }
  572. };
  573. return fn(false, '');
  574. }
  575. function readPlural(scnr) {
  576. skipSpaces(scnr);
  577. const plural = eat(scnr, "|" /* Pipe */);
  578. skipSpaces(scnr);
  579. return plural;
  580. }
  581. // TODO: We need refactoring of token parsing ...
  582. function readTokenInPlaceholder(scnr, context) {
  583. let token = null;
  584. const ch = scnr.currentChar();
  585. switch (ch) {
  586. case "{" /* BraceLeft */:
  587. if (context.braceNest >= 1) {
  588. emitError(8 /* NOT_ALLOW_NEST_PLACEHOLDER */, currentPosition(), 0);
  589. }
  590. scnr.next();
  591. token = getToken(context, 2 /* BraceLeft */, "{" /* BraceLeft */);
  592. skipSpaces(scnr);
  593. context.braceNest++;
  594. return token;
  595. case "}" /* BraceRight */:
  596. if (context.braceNest > 0 &&
  597. context.currentType === 2 /* BraceLeft */) {
  598. emitError(7 /* EMPTY_PLACEHOLDER */, currentPosition(), 0);
  599. }
  600. scnr.next();
  601. token = getToken(context, 3 /* BraceRight */, "}" /* BraceRight */);
  602. context.braceNest--;
  603. context.braceNest > 0 && skipSpaces(scnr);
  604. if (context.inLinked && context.braceNest === 0) {
  605. context.inLinked = false;
  606. }
  607. return token;
  608. case "@" /* LinkedAlias */:
  609. if (context.braceNest > 0) {
  610. emitError(6 /* UNTERMINATED_CLOSING_BRACE */, currentPosition(), 0);
  611. }
  612. token = readTokenInLinked(scnr, context) || getEndToken(context);
  613. context.braceNest = 0;
  614. return token;
  615. default:
  616. let validNamedIdentifier = true;
  617. let validListIdentifier = true;
  618. let validLiteral = true;
  619. if (isPluralStart(scnr)) {
  620. if (context.braceNest > 0) {
  621. emitError(6 /* UNTERMINATED_CLOSING_BRACE */, currentPosition(), 0);
  622. }
  623. token = getToken(context, 1 /* Pipe */, readPlural(scnr));
  624. // reset
  625. context.braceNest = 0;
  626. context.inLinked = false;
  627. return token;
  628. }
  629. if (context.braceNest > 0 &&
  630. (context.currentType === 5 /* Named */ ||
  631. context.currentType === 6 /* List */ ||
  632. context.currentType === 7 /* Literal */)) {
  633. emitError(6 /* UNTERMINATED_CLOSING_BRACE */, currentPosition(), 0);
  634. context.braceNest = 0;
  635. return readToken(scnr, context);
  636. }
  637. if ((validNamedIdentifier = isNamedIdentifierStart(scnr, context))) {
  638. token = getToken(context, 5 /* Named */, readNamedIdentifier(scnr));
  639. skipSpaces(scnr);
  640. return token;
  641. }
  642. if ((validListIdentifier = isListIdentifierStart(scnr, context))) {
  643. token = getToken(context, 6 /* List */, readListIdentifier(scnr));
  644. skipSpaces(scnr);
  645. return token;
  646. }
  647. if ((validLiteral = isLiteralStart(scnr, context))) {
  648. token = getToken(context, 7 /* Literal */, readLiteral(scnr));
  649. skipSpaces(scnr);
  650. return token;
  651. }
  652. if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
  653. // TODO: we should be re-designed invalid cases, when we will extend message syntax near the future ...
  654. token = getToken(context, 13 /* InvalidPlace */, readInvalidIdentifier(scnr));
  655. emitError(1 /* INVALID_TOKEN_IN_PLACEHOLDER */, currentPosition(), 0, token.value);
  656. skipSpaces(scnr);
  657. return token;
  658. }
  659. break;
  660. }
  661. return token;
  662. }
  663. // TODO: We need refactoring of token parsing ...
  664. function readTokenInLinked(scnr, context) {
  665. const { currentType } = context;
  666. let token = null;
  667. const ch = scnr.currentChar();
  668. if ((currentType === 8 /* LinkedAlias */ ||
  669. currentType === 9 /* LinkedDot */ ||
  670. currentType === 12 /* LinkedModifier */ ||
  671. currentType === 10 /* LinkedDelimiter */) &&
  672. (ch === CHAR_LF || ch === CHAR_SP)) {
  673. emitError(9 /* INVALID_LINKED_FORMAT */, currentPosition(), 0);
  674. }
  675. switch (ch) {
  676. case "@" /* LinkedAlias */:
  677. scnr.next();
  678. token = getToken(context, 8 /* LinkedAlias */, "@" /* LinkedAlias */);
  679. context.inLinked = true;
  680. return token;
  681. case "." /* LinkedDot */:
  682. skipSpaces(scnr);
  683. scnr.next();
  684. return getToken(context, 9 /* LinkedDot */, "." /* LinkedDot */);
  685. case ":" /* LinkedDelimiter */:
  686. skipSpaces(scnr);
  687. scnr.next();
  688. return getToken(context, 10 /* LinkedDelimiter */, ":" /* LinkedDelimiter */);
  689. default:
  690. if (isPluralStart(scnr)) {
  691. token = getToken(context, 1 /* Pipe */, readPlural(scnr));
  692. // reset
  693. context.braceNest = 0;
  694. context.inLinked = false;
  695. return token;
  696. }
  697. if (isLinkedDotStart(scnr, context) ||
  698. isLinkedDelimiterStart(scnr, context)) {
  699. skipSpaces(scnr);
  700. return readTokenInLinked(scnr, context);
  701. }
  702. if (isLinkedModifierStart(scnr, context)) {
  703. skipSpaces(scnr);
  704. return getToken(context, 12 /* LinkedModifier */, readLinkedModifier(scnr));
  705. }
  706. if (isLinkedReferStart(scnr, context)) {
  707. skipSpaces(scnr);
  708. if (ch === "{" /* BraceLeft */) {
  709. // scan the placeholder
  710. return readTokenInPlaceholder(scnr, context) || token;
  711. }
  712. else {
  713. return getToken(context, 11 /* LinkedKey */, readLinkedRefer(scnr));
  714. }
  715. }
  716. if (currentType === 8 /* LinkedAlias */) {
  717. emitError(9 /* INVALID_LINKED_FORMAT */, currentPosition(), 0);
  718. }
  719. context.braceNest = 0;
  720. context.inLinked = false;
  721. return readToken(scnr, context);
  722. }
  723. }
  724. // TODO: We need refactoring of token parsing ...
  725. function readToken(scnr, context) {
  726. let token = { type: 14 /* EOF */ };
  727. if (context.braceNest > 0) {
  728. return readTokenInPlaceholder(scnr, context) || getEndToken(context);
  729. }
  730. if (context.inLinked) {
  731. return readTokenInLinked(scnr, context) || getEndToken(context);
  732. }
  733. const ch = scnr.currentChar();
  734. switch (ch) {
  735. case "{" /* BraceLeft */:
  736. return readTokenInPlaceholder(scnr, context) || getEndToken(context);
  737. case "}" /* BraceRight */:
  738. emitError(5 /* UNBALANCED_CLOSING_BRACE */, currentPosition(), 0);
  739. scnr.next();
  740. return getToken(context, 3 /* BraceRight */, "}" /* BraceRight */);
  741. case "@" /* LinkedAlias */:
  742. return readTokenInLinked(scnr, context) || getEndToken(context);
  743. default:
  744. if (isPluralStart(scnr)) {
  745. token = getToken(context, 1 /* Pipe */, readPlural(scnr));
  746. // reset
  747. context.braceNest = 0;
  748. context.inLinked = false;
  749. return token;
  750. }
  751. if (isTextStart(scnr)) {
  752. return getToken(context, 0 /* Text */, readText(scnr));
  753. }
  754. if (ch === "%" /* Modulo */) {
  755. scnr.next();
  756. return getToken(context, 4 /* Modulo */, "%" /* Modulo */);
  757. }
  758. break;
  759. }
  760. return token;
  761. }
  762. function nextToken() {
  763. const { currentType, offset, startLoc, endLoc } = _context;
  764. _context.lastType = currentType;
  765. _context.lastOffset = offset;
  766. _context.lastStartLoc = startLoc;
  767. _context.lastEndLoc = endLoc;
  768. _context.offset = currentOffset();
  769. _context.startLoc = currentPosition();
  770. if (_scnr.currentChar() === EOF) {
  771. return getToken(_context, 14 /* EOF */);
  772. }
  773. return readToken(_scnr, _context);
  774. }
  775. return {
  776. nextToken,
  777. currentOffset,
  778. currentPosition,
  779. context
  780. };
  781. }
  782. const ERROR_DOMAIN = 'parser';
  783. // Backslash backslash, backslash quote, uHHHH, UHHHHHH.
  784. const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
  785. function fromEscapeSequence(match, codePoint4, codePoint6) {
  786. switch (match) {
  787. case `\\\\`:
  788. return `\\`;
  789. case `\\\'`:
  790. return `\'`;
  791. default: {
  792. const codePoint = parseInt(codePoint4 || codePoint6, 16);
  793. if (codePoint <= 0xd7ff || codePoint >= 0xe000) {
  794. return String.fromCodePoint(codePoint);
  795. }
  796. // invalid ...
  797. // Replace them with U+FFFD REPLACEMENT CHARACTER.
  798. return '�';
  799. }
  800. }
  801. }
  802. function createParser(options = {}) {
  803. const location = options.location !== false;
  804. const { onError } = options;
  805. function emitError(tokenzer, code, start, offset, ...args) {
  806. const end = tokenzer.currentPosition();
  807. end.offset += offset;
  808. end.column += offset;
  809. if (onError) {
  810. const loc = createLocation(start, end);
  811. const err = createCompileError(code, loc, {
  812. domain: ERROR_DOMAIN,
  813. args
  814. });
  815. onError(err);
  816. }
  817. }
  818. function startNode(type, offset, loc) {
  819. const node = {
  820. type,
  821. start: offset,
  822. end: offset
  823. };
  824. if (location) {
  825. node.loc = { start: loc, end: loc };
  826. }
  827. return node;
  828. }
  829. function endNode(node, offset, pos, type) {
  830. node.end = offset;
  831. if (type) {
  832. node.type = type;
  833. }
  834. if (location && node.loc) {
  835. node.loc.end = pos;
  836. }
  837. }
  838. function parseText(tokenizer, value) {
  839. const context = tokenizer.context();
  840. const node = startNode(3 /* Text */, context.offset, context.startLoc);
  841. node.value = value;
  842. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  843. return node;
  844. }
  845. function parseList(tokenizer, index) {
  846. const context = tokenizer.context();
  847. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  848. const node = startNode(5 /* List */, offset, loc);
  849. node.index = parseInt(index, 10);
  850. tokenizer.nextToken(); // skip brach right
  851. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  852. return node;
  853. }
  854. function parseNamed(tokenizer, key) {
  855. const context = tokenizer.context();
  856. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  857. const node = startNode(4 /* Named */, offset, loc);
  858. node.key = key;
  859. tokenizer.nextToken(); // skip brach right
  860. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  861. return node;
  862. }
  863. function parseLiteral(tokenizer, value) {
  864. const context = tokenizer.context();
  865. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  866. const node = startNode(9 /* Literal */, offset, loc);
  867. node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
  868. tokenizer.nextToken(); // skip brach right
  869. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  870. return node;
  871. }
  872. function parseLinkedModifier(tokenizer) {
  873. const token = tokenizer.nextToken();
  874. const context = tokenizer.context();
  875. const { lastOffset: offset, lastStartLoc: loc } = context; // get linked dot loc
  876. const node = startNode(8 /* LinkedModifier */, offset, loc);
  877. if (token.type !== 12 /* LinkedModifier */) {
  878. // empty modifier
  879. emitError(tokenizer, 11 /* UNEXPECTED_EMPTY_LINKED_MODIFIER */, context.lastStartLoc, 0);
  880. node.value = '';
  881. endNode(node, offset, loc);
  882. return {
  883. nextConsumeToken: token,
  884. node
  885. };
  886. }
  887. // check token
  888. if (token.value == null) {
  889. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  890. }
  891. node.value = token.value || '';
  892. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  893. return {
  894. node
  895. };
  896. }
  897. function parseLinkedKey(tokenizer, value) {
  898. const context = tokenizer.context();
  899. const node = startNode(7 /* LinkedKey */, context.offset, context.startLoc);
  900. node.value = value;
  901. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  902. return node;
  903. }
  904. function parseLinked(tokenizer) {
  905. const context = tokenizer.context();
  906. const linkedNode = startNode(6 /* Linked */, context.offset, context.startLoc);
  907. let token = tokenizer.nextToken();
  908. if (token.type === 9 /* LinkedDot */) {
  909. const parsed = parseLinkedModifier(tokenizer);
  910. linkedNode.modifier = parsed.node;
  911. token = parsed.nextConsumeToken || tokenizer.nextToken();
  912. }
  913. // asset check token
  914. if (token.type !== 10 /* LinkedDelimiter */) {
  915. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  916. }
  917. token = tokenizer.nextToken();
  918. // skip brace left
  919. if (token.type === 2 /* BraceLeft */) {
  920. token = tokenizer.nextToken();
  921. }
  922. switch (token.type) {
  923. case 11 /* LinkedKey */:
  924. if (token.value == null) {
  925. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  926. }
  927. linkedNode.key = parseLinkedKey(tokenizer, token.value || '');
  928. break;
  929. case 5 /* Named */:
  930. if (token.value == null) {
  931. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  932. }
  933. linkedNode.key = parseNamed(tokenizer, token.value || '');
  934. break;
  935. case 6 /* List */:
  936. if (token.value == null) {
  937. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  938. }
  939. linkedNode.key = parseList(tokenizer, token.value || '');
  940. break;
  941. case 7 /* Literal */:
  942. if (token.value == null) {
  943. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  944. }
  945. linkedNode.key = parseLiteral(tokenizer, token.value || '');
  946. break;
  947. default:
  948. // empty key
  949. emitError(tokenizer, 12 /* UNEXPECTED_EMPTY_LINKED_KEY */, context.lastStartLoc, 0);
  950. const nextContext = tokenizer.context();
  951. const emptyLinkedKeyNode = startNode(7 /* LinkedKey */, nextContext.offset, nextContext.startLoc);
  952. emptyLinkedKeyNode.value = '';
  953. endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
  954. linkedNode.key = emptyLinkedKeyNode;
  955. endNode(linkedNode, nextContext.offset, nextContext.startLoc);
  956. return {
  957. nextConsumeToken: token,
  958. node: linkedNode
  959. };
  960. }
  961. endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
  962. return {
  963. node: linkedNode
  964. };
  965. }
  966. function parseMessage(tokenizer) {
  967. const context = tokenizer.context();
  968. const startOffset = context.currentType === 1 /* Pipe */
  969. ? tokenizer.currentOffset()
  970. : context.offset;
  971. const startLoc = context.currentType === 1 /* Pipe */
  972. ? context.endLoc
  973. : context.startLoc;
  974. const node = startNode(2 /* Message */, startOffset, startLoc);
  975. node.items = [];
  976. let nextToken = null;
  977. do {
  978. const token = nextToken || tokenizer.nextToken();
  979. nextToken = null;
  980. switch (token.type) {
  981. case 0 /* Text */:
  982. if (token.value == null) {
  983. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  984. }
  985. node.items.push(parseText(tokenizer, token.value || ''));
  986. break;
  987. case 6 /* List */:
  988. if (token.value == null) {
  989. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  990. }
  991. node.items.push(parseList(tokenizer, token.value || ''));
  992. break;
  993. case 5 /* Named */:
  994. if (token.value == null) {
  995. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  996. }
  997. node.items.push(parseNamed(tokenizer, token.value || ''));
  998. break;
  999. case 7 /* Literal */:
  1000. if (token.value == null) {
  1001. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, getTokenCaption(token));
  1002. }
  1003. node.items.push(parseLiteral(tokenizer, token.value || ''));
  1004. break;
  1005. case 8 /* LinkedAlias */:
  1006. const parsed = parseLinked(tokenizer);
  1007. node.items.push(parsed.node);
  1008. nextToken = parsed.nextConsumeToken || null;
  1009. break;
  1010. }
  1011. } while (context.currentType !== 14 /* EOF */ &&
  1012. context.currentType !== 1 /* Pipe */);
  1013. // adjust message node loc
  1014. const endOffset = context.currentType === 1 /* Pipe */
  1015. ? context.lastOffset
  1016. : tokenizer.currentOffset();
  1017. const endLoc = context.currentType === 1 /* Pipe */
  1018. ? context.lastEndLoc
  1019. : tokenizer.currentPosition();
  1020. endNode(node, endOffset, endLoc);
  1021. return node;
  1022. }
  1023. function parsePlural(tokenizer, offset, loc, msgNode) {
  1024. const context = tokenizer.context();
  1025. let hasEmptyMessage = msgNode.items.length === 0;
  1026. const node = startNode(1 /* Plural */, offset, loc);
  1027. node.cases = [];
  1028. node.cases.push(msgNode);
  1029. do {
  1030. const msg = parseMessage(tokenizer);
  1031. if (!hasEmptyMessage) {
  1032. hasEmptyMessage = msg.items.length === 0;
  1033. }
  1034. node.cases.push(msg);
  1035. } while (context.currentType !== 14 /* EOF */);
  1036. if (hasEmptyMessage) {
  1037. emitError(tokenizer, 10 /* MUST_HAVE_MESSAGES_IN_PLURAL */, loc, 0);
  1038. }
  1039. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1040. return node;
  1041. }
  1042. function parseResource(tokenizer) {
  1043. const context = tokenizer.context();
  1044. const { offset, startLoc } = context;
  1045. const msgNode = parseMessage(tokenizer);
  1046. if (context.currentType === 14 /* EOF */) {
  1047. return msgNode;
  1048. }
  1049. else {
  1050. return parsePlural(tokenizer, offset, startLoc, msgNode);
  1051. }
  1052. }
  1053. function parse(source) {
  1054. const tokenizer = createTokenizer(source, shared.assign({}, options));
  1055. const context = tokenizer.context();
  1056. const node = startNode(0 /* Resource */, context.offset, context.startLoc);
  1057. if (location && node.loc) {
  1058. node.loc.source = source;
  1059. }
  1060. node.body = parseResource(tokenizer);
  1061. // assert whether achieved to EOF
  1062. if (context.currentType !== 14 /* EOF */) {
  1063. emitError(tokenizer, 13 /* UNEXPECTED_LEXICAL_ANALYSIS */, context.lastStartLoc, 0, source[context.offset] || '');
  1064. }
  1065. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1066. return node;
  1067. }
  1068. return { parse };
  1069. }
  1070. function getTokenCaption(token) {
  1071. if (token.type === 14 /* EOF */) {
  1072. return 'EOF';
  1073. }
  1074. const name = (token.value || '').replace(/\r?\n/gu, '\\n');
  1075. return name.length > 10 ? name.slice(0, 9) + '…' : name;
  1076. }
  1077. function createTransformer(ast, options = {} // eslint-disable-line
  1078. ) {
  1079. const _context = {
  1080. ast,
  1081. helpers: new Set()
  1082. };
  1083. const context = () => _context;
  1084. const helper = (name) => {
  1085. _context.helpers.add(name);
  1086. return name;
  1087. };
  1088. return { context, helper };
  1089. }
  1090. function traverseNodes(nodes, transformer) {
  1091. for (let i = 0; i < nodes.length; i++) {
  1092. traverseNode(nodes[i], transformer);
  1093. }
  1094. }
  1095. function traverseNode(node, transformer) {
  1096. // TODO: if we need pre-hook of transform, should be implemented to here
  1097. switch (node.type) {
  1098. case 1 /* Plural */:
  1099. traverseNodes(node.cases, transformer);
  1100. transformer.helper("plural" /* PLURAL */);
  1101. break;
  1102. case 2 /* Message */:
  1103. traverseNodes(node.items, transformer);
  1104. break;
  1105. case 6 /* Linked */:
  1106. const linked = node;
  1107. traverseNode(linked.key, transformer);
  1108. transformer.helper("linked" /* LINKED */);
  1109. break;
  1110. case 5 /* List */:
  1111. transformer.helper("interpolate" /* INTERPOLATE */);
  1112. transformer.helper("list" /* LIST */);
  1113. break;
  1114. case 4 /* Named */:
  1115. transformer.helper("interpolate" /* INTERPOLATE */);
  1116. transformer.helper("named" /* NAMED */);
  1117. break;
  1118. }
  1119. // TODO: if we need post-hook of transform, should be implemented to here
  1120. }
  1121. // transform AST
  1122. function transform(ast, options = {} // eslint-disable-line
  1123. ) {
  1124. const transformer = createTransformer(ast);
  1125. transformer.helper("normalize" /* NORMALIZE */);
  1126. // traverse
  1127. ast.body && traverseNode(ast.body, transformer);
  1128. // set meta information
  1129. const context = transformer.context();
  1130. ast.helpers = Array.from(context.helpers);
  1131. }
  1132. function createCodeGenerator(ast, options) {
  1133. const { sourceMap: sourceMap$1, filename, breakLineCode, needIndent: _needIndent } = options;
  1134. const _context = {
  1135. source: ast.loc.source,
  1136. filename,
  1137. code: '',
  1138. column: 1,
  1139. line: 1,
  1140. offset: 0,
  1141. map: undefined,
  1142. breakLineCode,
  1143. needIndent: _needIndent,
  1144. indentLevel: 0
  1145. };
  1146. const context = () => _context;
  1147. function push(code, node) {
  1148. _context.code += code;
  1149. if (_context.map) {
  1150. if (node && node.loc && node.loc !== LocationStub) {
  1151. addMapping(node.loc.start, getMappingName(node));
  1152. }
  1153. advancePositionWithSource(_context, code);
  1154. }
  1155. }
  1156. function _newline(n, withBreakLine = true) {
  1157. const _breakLineCode = withBreakLine ? breakLineCode : '';
  1158. push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
  1159. }
  1160. function indent(withNewLine = true) {
  1161. const level = ++_context.indentLevel;
  1162. withNewLine && _newline(level);
  1163. }
  1164. function deindent(withNewLine = true) {
  1165. const level = --_context.indentLevel;
  1166. withNewLine && _newline(level);
  1167. }
  1168. function newline() {
  1169. _newline(_context.indentLevel);
  1170. }
  1171. const helper = (key) => `_${key}`;
  1172. const needIndent = () => _context.needIndent;
  1173. function addMapping(loc, name) {
  1174. _context.map.addMapping({
  1175. name,
  1176. source: _context.filename,
  1177. original: {
  1178. line: loc.line,
  1179. column: loc.column - 1
  1180. },
  1181. generated: {
  1182. line: _context.line,
  1183. column: _context.column - 1
  1184. }
  1185. });
  1186. }
  1187. if (sourceMap$1) {
  1188. _context.map = new sourceMap.SourceMapGenerator();
  1189. _context.map.setSourceContent(filename, _context.source);
  1190. }
  1191. return {
  1192. context,
  1193. push,
  1194. indent,
  1195. deindent,
  1196. newline,
  1197. helper,
  1198. needIndent
  1199. };
  1200. }
  1201. function generateLinkedNode(generator, node) {
  1202. const { helper } = generator;
  1203. generator.push(`${helper("linked" /* LINKED */)}(`);
  1204. generateNode(generator, node.key);
  1205. if (node.modifier) {
  1206. generator.push(`, `);
  1207. generateNode(generator, node.modifier);
  1208. }
  1209. generator.push(`)`);
  1210. }
  1211. function generateMessageNode(generator, node) {
  1212. const { helper, needIndent } = generator;
  1213. generator.push(`${helper("normalize" /* NORMALIZE */)}([`);
  1214. generator.indent(needIndent());
  1215. const length = node.items.length;
  1216. for (let i = 0; i < length; i++) {
  1217. generateNode(generator, node.items[i]);
  1218. if (i === length - 1) {
  1219. break;
  1220. }
  1221. generator.push(', ');
  1222. }
  1223. generator.deindent(needIndent());
  1224. generator.push('])');
  1225. }
  1226. function generatePluralNode(generator, node) {
  1227. const { helper, needIndent } = generator;
  1228. if (node.cases.length > 1) {
  1229. generator.push(`${helper("plural" /* PLURAL */)}([`);
  1230. generator.indent(needIndent());
  1231. const length = node.cases.length;
  1232. for (let i = 0; i < length; i++) {
  1233. generateNode(generator, node.cases[i]);
  1234. if (i === length - 1) {
  1235. break;
  1236. }
  1237. generator.push(', ');
  1238. }
  1239. generator.deindent(needIndent());
  1240. generator.push(`])`);
  1241. }
  1242. }
  1243. function generateResource(generator, node) {
  1244. if (node.body) {
  1245. generateNode(generator, node.body);
  1246. }
  1247. else {
  1248. generator.push('null');
  1249. }
  1250. }
  1251. function generateNode(generator, node) {
  1252. const { helper } = generator;
  1253. switch (node.type) {
  1254. case 0 /* Resource */:
  1255. generateResource(generator, node);
  1256. break;
  1257. case 1 /* Plural */:
  1258. generatePluralNode(generator, node);
  1259. break;
  1260. case 2 /* Message */:
  1261. generateMessageNode(generator, node);
  1262. break;
  1263. case 6 /* Linked */:
  1264. generateLinkedNode(generator, node);
  1265. break;
  1266. case 8 /* LinkedModifier */:
  1267. generator.push(JSON.stringify(node.value), node);
  1268. break;
  1269. case 7 /* LinkedKey */:
  1270. generator.push(JSON.stringify(node.value), node);
  1271. break;
  1272. case 5 /* List */:
  1273. generator.push(`${helper("interpolate" /* INTERPOLATE */)}(${helper("list" /* LIST */)}(${node.index}))`, node);
  1274. break;
  1275. case 4 /* Named */:
  1276. generator.push(`${helper("interpolate" /* INTERPOLATE */)}(${helper("named" /* NAMED */)}(${JSON.stringify(node.key)}))`, node);
  1277. break;
  1278. case 9 /* Literal */:
  1279. generator.push(JSON.stringify(node.value), node);
  1280. break;
  1281. case 3 /* Text */:
  1282. generator.push(JSON.stringify(node.value), node);
  1283. break;
  1284. }
  1285. }
  1286. // generate code from AST
  1287. const generate = (ast, options = {} // eslint-disable-line
  1288. ) => {
  1289. const mode = shared.isString(options.mode) ? options.mode : 'normal';
  1290. const filename = shared.isString(options.filename)
  1291. ? options.filename
  1292. : 'message.intl';
  1293. const sourceMap = !!options.sourceMap;
  1294. // prettier-ignore
  1295. const breakLineCode = options.breakLineCode != null
  1296. ? options.breakLineCode
  1297. : mode === 'arrow'
  1298. ? ';'
  1299. : '\n';
  1300. const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
  1301. const helpers = ast.helpers || [];
  1302. const generator = createCodeGenerator(ast, {
  1303. mode,
  1304. filename,
  1305. sourceMap,
  1306. breakLineCode,
  1307. needIndent
  1308. });
  1309. generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
  1310. generator.indent(needIndent);
  1311. if (helpers.length > 0) {
  1312. generator.push(`const { ${helpers.map(s => `${s}: _${s}`).join(', ')} } = ctx`);
  1313. generator.newline();
  1314. }
  1315. generator.push(`return `);
  1316. generateNode(generator, ast);
  1317. generator.deindent(needIndent);
  1318. generator.push(`}`);
  1319. const { code, map } = generator.context();
  1320. return {
  1321. ast,
  1322. code,
  1323. map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
  1324. };
  1325. };
  1326. function getMappingName(node) {
  1327. switch (node.type) {
  1328. case 3 /* Text */:
  1329. return node.value;
  1330. case 5 /* List */:
  1331. return node.index.toString();
  1332. case 4 /* Named */:
  1333. return node.key;
  1334. case 9 /* Literal */:
  1335. return node.value;
  1336. case 8 /* LinkedModifier */:
  1337. return node.value;
  1338. case 7 /* LinkedKey */:
  1339. return node.value;
  1340. default:
  1341. return undefined;
  1342. }
  1343. }
  1344. function advancePositionWithSource(pos, source, numberOfCharacters = source.length) {
  1345. let linesCount = 0;
  1346. let lastNewLinePos = -1;
  1347. for (let i = 0; i < numberOfCharacters; i++) {
  1348. if (source.charCodeAt(i) === 10 /* newline char code */) {
  1349. linesCount++;
  1350. lastNewLinePos = i;
  1351. }
  1352. }
  1353. pos.offset += numberOfCharacters;
  1354. pos.line += linesCount;
  1355. pos.column =
  1356. lastNewLinePos === -1
  1357. ? pos.column + numberOfCharacters
  1358. : numberOfCharacters - lastNewLinePos;
  1359. return pos;
  1360. }
  1361. function baseCompile(source, options = {}) {
  1362. const assignedOptions = shared.assign({}, options);
  1363. // parse source codes
  1364. const parser = createParser(assignedOptions);
  1365. const ast = parser.parse(source);
  1366. // transform ASTs
  1367. transform(ast, assignedOptions);
  1368. // generate javascript codes
  1369. return generate(ast, assignedOptions);
  1370. }
  1371. exports.ERROR_DOMAIN = ERROR_DOMAIN;
  1372. exports.LocationStub = LocationStub;
  1373. exports.baseCompile = baseCompile;
  1374. exports.createCompileError = createCompileError;
  1375. exports.createLocation = createLocation;
  1376. exports.createParser = createParser;
  1377. exports.createPosition = createPosition;
  1378. exports.defaultOnError = defaultOnError;
  1379. exports.errorMessages = errorMessages;