@tolgee/cli 2.1.7 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/cli.js +3 -3
  2. package/dist/extractor/extractor.js +11 -4
  3. package/dist/extractor/parser/extractComment.js +7 -10
  4. package/dist/extractor/parser/generalMapper.js +4 -4
  5. package/dist/extractor/parser/mergerMachine.js +42 -11
  6. package/dist/extractor/parser/tokenMergers/closingTagMerger.js +1 -1
  7. package/dist/extractor/parser/tokenMergers/commentsMerger.js +8 -5
  8. package/dist/extractor/parser/tokenMergers/stringMerger.js +5 -5
  9. package/dist/extractor/parser/tokenMergers/templateStringMerger.js +1 -1
  10. package/dist/extractor/parser/tree/getTranslateProps.js +1 -1
  11. package/dist/extractor/parserNgx/ParserNgx.js +29 -0
  12. package/dist/extractor/parserNgx/ngxMapper.js +67 -0
  13. package/dist/extractor/parserNgx/ngxTreeTransform.js +46 -0
  14. package/dist/extractor/parserNgx/rules/componentWithT.js +43 -0
  15. package/dist/extractor/parserNgx/rules/helpers/parsePipeArgs.js +26 -0
  16. package/dist/extractor/parserNgx/rules/translateFunction.js +7 -0
  17. package/dist/extractor/parserNgx/rules/translatePipe.js +57 -0
  18. package/dist/extractor/parserNgx/tokenMergers/elementMerger.js +29 -0
  19. package/dist/extractor/parserNgx/tokenMergers/pipeMerger.js +19 -0
  20. package/dist/extractor/parserNgx/tokenMergers/translateMerger.js +41 -0
  21. package/dist/extractor/parserSvelte/svelteMapper.js +2 -2
  22. package/dist/extractor/parserVue/vueMapper.js +2 -2
  23. package/dist/extractor/runner.js +11 -1
  24. package/dist/extractor/tokenizer.js +12 -6
  25. package/dist/options.js +1 -1
  26. package/extractor.d.ts +1 -1
  27. package/package.json +1 -1
  28. package/schema.json +1 -1
  29. package/textmate/AngularHtml.tmLanguage +1 -0
  30. package/textmate/THIRD_PARTY_NOTICE +32 -0
package/dist/cli.js CHANGED
@@ -60,14 +60,14 @@ function loadProjectId(cmd) {
60
60
  }
61
61
  function validateOptions(cmd) {
62
62
  const opts = cmd.optsWithGlobals();
63
+ if (!opts.apiKey) {
64
+ exitWithError('No API key has been provided. You must either provide one via --api-key, or login via `tolgee login`.');
65
+ }
63
66
  if (opts.projectId === -1) {
64
67
  error('No Project ID have been specified. You must either provide one via --project-id, or by setting up a `.tolgeerc` file.');
65
68
  info('Learn more about configuring the CLI here: https://tolgee.io/tolgee-cli/project-configuration');
66
69
  process.exit(1);
67
70
  }
68
- if (!opts.apiKey) {
69
- exitWithError('No API key has been provided. You must either provide one via --api-key, or login via `tolgee login`.');
70
- }
71
71
  }
72
72
  const preHandler = (config) => async function (prog, cmd) {
73
73
  if (!NO_KEY_COMMANDS.includes(topLevelName(cmd))) {
@@ -3,6 +3,7 @@ import { ParserReact } from './parserReact/ParserReact.js';
3
3
  import { tokensList } from './visualizers/printTokens.js';
4
4
  import { visualizeRules } from './visualizers/visualizeRules.js';
5
5
  import { ParserVue } from './parserVue/ParserVue.js';
6
+ import { ParserNgx } from './parserNgx/ParserNgx.js';
6
7
  import { ParserSvelte } from './parserSvelte/ParserSvelte.js';
7
8
  function pickParser(format) {
8
9
  switch (format) {
@@ -12,6 +13,8 @@ function pickParser(format) {
12
13
  return ParserVue();
13
14
  case 'svelte':
14
15
  return ParserSvelte();
16
+ case 'ngx':
17
+ return ParserNgx();
15
18
  }
16
19
  }
17
20
  export async function extractTreeAndReport(code, fileName, parserType, options) {
@@ -33,10 +36,14 @@ export async function extractTreeAndReport(code, fileName, parserType, options)
33
36
  options,
34
37
  });
35
38
  if (debug) {
36
- console.log(JSON.stringify(result.tree, null, 2));
37
- console.log(tokensList(tokensMerged));
38
- console.log(visualizeRules(tokensMerged, code));
39
- console.log(visualizeRules(tokensWithRules, code));
39
+ console.log(JSON.stringify(result.tree, null, 2) +
40
+ '\n' +
41
+ tokensList(tokensMerged) +
42
+ '\n' +
43
+ visualizeRules(tokensMerged, code) +
44
+ '\n' +
45
+ visualizeRules(tokensWithRules, code) +
46
+ '\n');
40
47
  }
41
48
  return result;
42
49
  }
@@ -14,16 +14,13 @@ function isValidKeyOverride(data) {
14
14
  }
15
15
  return true;
16
16
  }
17
- function getEndLine(token) {
18
- return token.line + (token.token.match(/\n/gm)?.length ?? 0);
19
- }
20
17
  export function extractComment(token) {
21
- const comment = token.token.trim();
18
+ const comment = token.token.replaceAll(/[^\n]([\w]*\*+)/g, '').trim();
22
19
  if (comment.startsWith('@tolgee-ignore')) {
23
20
  return {
24
21
  type: 'MAGIC_COMMENT',
25
22
  kind: 'ignore',
26
- line: getEndLine(token),
23
+ line: token.line,
27
24
  };
28
25
  }
29
26
  if (comment.startsWith('@tolgee-key')) {
@@ -34,7 +31,7 @@ export function extractComment(token) {
34
31
  type: 'MAGIC_COMMENT',
35
32
  kind: 'key',
36
33
  keyName: data.slice(1),
37
- line: getEndLine(token),
34
+ line: token.line,
38
35
  };
39
36
  }
40
37
  // Data is a json5 struct
@@ -46,7 +43,7 @@ export function extractComment(token) {
46
43
  return {
47
44
  type: 'WARNING',
48
45
  kind: 'W_INVALID_KEY_OVERRIDE',
49
- line: getEndLine(token),
46
+ line: token.line,
50
47
  };
51
48
  }
52
49
  else {
@@ -56,7 +53,7 @@ export function extractComment(token) {
56
53
  keyName: key.key,
57
54
  namespace: key.ns,
58
55
  defaultValue: key.defaultValue,
59
- line: getEndLine(token),
56
+ line: token.line,
60
57
  };
61
58
  }
62
59
  }
@@ -64,7 +61,7 @@ export function extractComment(token) {
64
61
  return {
65
62
  type: 'WARNING',
66
63
  kind: 'W_MALFORMED_KEY_OVERRIDE',
67
- line: getEndLine(token),
64
+ line: token.line,
68
65
  };
69
66
  }
70
67
  }
@@ -72,7 +69,7 @@ export function extractComment(token) {
72
69
  type: 'MAGIC_COMMENT',
73
70
  kind: 'key',
74
71
  keyName: data,
75
- line: getEndLine(token),
72
+ line: token.line,
76
73
  };
77
74
  }
78
75
  }
@@ -13,9 +13,9 @@ export const generalMapper = (token) => {
13
13
  return 'primitive.null';
14
14
  // plain strings
15
15
  case 'punctuation.definition.string.begin.ts':
16
- return 'string.begin';
16
+ return 'string.quote';
17
17
  case 'punctuation.definition.string.end.ts':
18
- return 'string.end';
18
+ return 'string.quote';
19
19
  case 'string.quoted.single.ts':
20
20
  case 'string.quoted.double.ts':
21
21
  return 'string.body';
@@ -23,9 +23,9 @@ export const generalMapper = (token) => {
23
23
  return 'escaped.character';
24
24
  // template strings
25
25
  case 'punctuation.definition.string.template.begin.ts':
26
- return 'string.teplate.begin';
26
+ return 'string.teplate.quote';
27
27
  case 'punctuation.definition.string.template.end.ts':
28
- return 'string.template.end';
28
+ return 'string.template.quote';
29
29
  case 'string.template.ts':
30
30
  return 'string.template.body';
31
31
  // variables
@@ -1,13 +1,15 @@
1
- function defaultResultToken(matched) {
2
- return matched.map((t) => t.token).join('');
3
- }
4
1
  const MERGE_ALL = Symbol('MERGE_ALL');
5
2
  const MERGE_WITHOUT_LAST = Symbol('MERGE_WITHOUT_LAST');
3
+ const REPLACE_FIRST = Symbol('REPLACE_FIRST');
4
+ const MERGE_CUSTOM = Symbol('MERGE_CUSTOM');
6
5
  export const endOptions = {
7
6
  MERGE_ALL,
8
7
  MERGE_WITHOUT_LAST,
8
+ REPLACE_FIRST,
9
+ MERGE_CUSTOM,
9
10
  };
10
11
  function createNewToken(tokens, customType, merger) {
12
+ const mergerData = merger?.(tokens);
11
13
  return {
12
14
  customType,
13
15
  type: 'custom',
@@ -15,7 +17,8 @@ function createNewToken(tokens, customType, merger) {
15
17
  endIndex: tokens[tokens.length - 1].endIndex,
16
18
  scopes: [],
17
19
  line: tokens[0].line,
18
- token: merger(tokens),
20
+ token: tokens.map((t) => t.token).join(''),
21
+ ...mergerData,
19
22
  };
20
23
  }
21
24
  export function createMachine(machine) {
@@ -34,15 +37,43 @@ export function createMachine(machine) {
34
37
  continue;
35
38
  }
36
39
  else if (newState === endOptions.MERGE_ALL ||
37
- newState === endOptions.MERGE_WITHOUT_LAST) {
38
- const lastToken = newState === endOptions.MERGE_WITHOUT_LAST ? stack.pop() : undefined;
39
- const newToken = createNewToken(stack, machine.customType, machine.resultToken ?? defaultResultToken);
40
- state = machine.initial;
41
- stack = [];
40
+ newState === endOptions.MERGE_WITHOUT_LAST ||
41
+ newState === endOptions.REPLACE_FIRST ||
42
+ newState === endOptions.MERGE_CUSTOM) {
43
+ let before = [];
44
+ let toMerge;
45
+ let after;
46
+ if (newState === endOptions.MERGE_ALL) {
47
+ toMerge = stack;
48
+ after = [];
49
+ }
50
+ else if (newState === endOptions.MERGE_WITHOUT_LAST) {
51
+ after = [stack.pop()];
52
+ toMerge = stack;
53
+ }
54
+ else if (newState === endOptions.REPLACE_FIRST) {
55
+ toMerge = [stack.shift()];
56
+ after = stack;
57
+ }
58
+ else {
59
+ if (!machine.customMerge) {
60
+ throw new Error('No custom merge cpecified');
61
+ }
62
+ const result = machine.customMerge(stack);
63
+ before = result.before;
64
+ toMerge = result.toMerge;
65
+ after = result.after;
66
+ }
67
+ const newToken = createNewToken(toMerge, machine.customType, machine.resultToken);
68
+ for (const result of before) {
69
+ yield result;
70
+ }
42
71
  yield newToken;
43
- if (lastToken) {
44
- yield lastToken;
72
+ for (const result of after) {
73
+ yield result;
45
74
  }
75
+ stack = [];
76
+ state = machine.initial;
46
77
  continue;
47
78
  }
48
79
  else {
@@ -22,6 +22,6 @@ export const closingTagMerger = {
22
22
  },
23
23
  customType: 'tag.closing',
24
24
  resultToken: (matched) => {
25
- return matched[1].token;
25
+ return { token: matched[1].token };
26
26
  },
27
27
  };
@@ -12,7 +12,7 @@ export const commentsMerger = {
12
12
  if (type === 'comment.line') {
13
13
  return end.MERGE_ALL;
14
14
  }
15
- else if (type === 'comment.block') {
15
+ else if (type === 'comment.block' || token.token === '\n') {
16
16
  return 2 /* S.CommentBlock */;
17
17
  }
18
18
  break;
@@ -27,10 +27,13 @@ export const commentsMerger = {
27
27
  }
28
28
  },
29
29
  resultToken: (matched) => {
30
- return matched
31
- .filter((t) => t.customType && t.customType !== 'comment.definition')
32
- .map((t) => t.token)
33
- .join('');
30
+ return {
31
+ token: matched
32
+ .filter((t) => t.customType && t.customType !== 'comment.definition')
33
+ .map((t) => t.token)
34
+ .join(''),
35
+ line: matched[matched.length - 1].line,
36
+ };
34
37
  },
35
38
  customType: 'comment',
36
39
  };
@@ -5,10 +5,10 @@ export const stringMerger = {
5
5
  const type = token.customType;
6
6
  switch (state) {
7
7
  case 0 /* S.Idle */:
8
- if (type === 'string.begin') {
8
+ if (type === 'string.quote') {
9
9
  return 1 /* S.RegularString */;
10
10
  }
11
- else if (type === 'string.teplate.begin') {
11
+ else if (type === 'string.teplate.quote') {
12
12
  return 2 /* S.TemplateString */;
13
13
  }
14
14
  break;
@@ -19,7 +19,7 @@ export const stringMerger = {
19
19
  else if (type === 'escaped.character') {
20
20
  return 1 /* S.RegularString */;
21
21
  }
22
- else if (type === 'string.end') {
22
+ else if (type === 'string.quote') {
23
23
  return end.MERGE_ALL;
24
24
  }
25
25
  break;
@@ -30,7 +30,7 @@ export const stringMerger = {
30
30
  else if (type === 'escaped.character') {
31
31
  return 2 /* S.TemplateString */;
32
32
  }
33
- else if (type === 'string.template.end') {
33
+ else if (type === 'string.template.quote') {
34
34
  return end.MERGE_ALL;
35
35
  }
36
36
  break;
@@ -50,6 +50,6 @@ export const stringMerger = {
50
50
  }
51
51
  })
52
52
  .join('');
53
- return unescape(escaped);
53
+ return { token: unescape(escaped) };
54
54
  },
55
55
  };
@@ -50,6 +50,6 @@ export const templateStringMerger = {
50
50
  result.push(token.token);
51
51
  }
52
52
  }
53
- return result.join('').trim();
53
+ return { token: result.join('').trim() };
54
54
  },
55
55
  };
@@ -1,4 +1,4 @@
1
- function getCombinedOptions({ ns, noWrap, orEmpty, params, language, ...rest }, line) {
1
+ export function getCombinedOptions({ ns, noWrap, orEmpty, params, language, ...rest }, line) {
2
2
  const options = {
3
3
  ns: ns,
4
4
  noWrap: noWrap,
@@ -0,0 +1,29 @@
1
+ import { pipeMachines } from '../parser/mergerMachine.js';
2
+ import { DEFAULT_BLOCKS, DEFAULT_MERGERERS, Parser } from '../parser/parser.js';
3
+ import { generalMapper } from '../parser/generalMapper.js';
4
+ import { ngxMapper } from './ngxMapper.js';
5
+ import { ngxTreeTransform } from './ngxTreeTransform.js';
6
+ import { componentWithTMerger } from './tokenMergers/elementMerger.js';
7
+ import { translateMerger } from './tokenMergers/translateMerger.js';
8
+ import { pipeMerger } from './tokenMergers/pipeMerger.js';
9
+ import { componentWithT } from './rules/componentWithT.js';
10
+ import { translatePipe } from './rules/translatePipe.js';
11
+ import { translateFunction } from './rules/translateFunction.js';
12
+ const ngxMappers = [ngxMapper, generalMapper];
13
+ export const ngxMergers = pipeMachines([
14
+ ...DEFAULT_MERGERERS,
15
+ componentWithTMerger,
16
+ pipeMerger,
17
+ translateMerger,
18
+ ]);
19
+ export const ParserNgx = () => {
20
+ return Parser({
21
+ mappers: ngxMappers,
22
+ blocks: {
23
+ ...DEFAULT_BLOCKS,
24
+ },
25
+ rules: [componentWithT, translatePipe, translateFunction],
26
+ merger: ngxMergers,
27
+ treeTransform: ngxTreeTransform,
28
+ });
29
+ };
@@ -0,0 +1,67 @@
1
+ export const ngxMapper = (token) => {
2
+ switch (token.type) {
3
+ // ngx template tags
4
+ case 'punctuation.definition.tag.begin.html':
5
+ return token.token === '</' ? 'tag.closing.begin' : 'tag.regular.begin';
6
+ case 'punctuation.definition.tag.end.html':
7
+ return token.token === '/>' ? 'tag.self-closing.end' : 'tag.regular.end';
8
+ case 'html-template.tag.html':
9
+ return 'tag.name';
10
+ case 'html-template.ng.attributes.generic':
11
+ return 'tag.attribute.name';
12
+ case 'punctuation.separator.key-value.html-template.ng':
13
+ return 'operator.assignment';
14
+ case 'entity.other.attribute-name.html':
15
+ return 'tag.attribute.name';
16
+ case 'punctuation.separator.key-value.html':
17
+ return 'operator.assignment';
18
+ // html string attributes
19
+ case 'punctuation.definition.string.begin.html':
20
+ return 'string.quote';
21
+ case 'punctuation.definition.string.end.html':
22
+ return 'string.quote';
23
+ case 'string.quoted.single.html':
24
+ case 'string.quoted.double.html':
25
+ if (token.token === '"' || token.token === "'") {
26
+ // ignoring qotes around strings and expressions
27
+ // we can just take the content without them
28
+ // as otherwise we would need to distinguish if it's an expression or string
29
+ // (angular grammar doesn't do this for some reason)
30
+ return 'ignore';
31
+ }
32
+ else {
33
+ return 'string';
34
+ }
35
+ case 'string.unquoted.html':
36
+ return 'string';
37
+ case 'html-template.ng.attributes.input-binding.first-level':
38
+ case 'html-template.ng.attributes.event-handler':
39
+ return 'tag.attribute.name';
40
+ case 'punctuation.definition.ng-binding-name.begin.html':
41
+ case 'punctuation.definition.ng-binding-name.end.html':
42
+ // ignoring binding brackets, irrelevant for us
43
+ return 'ignore';
44
+ // html comments
45
+ case 'punctuation.definition.comment.begin.html':
46
+ case 'punctuation.definition.comment.end.html':
47
+ case 'punctuation.definition.comment.html':
48
+ return 'comment.definition';
49
+ case 'comment.block.html':
50
+ return 'comment.block';
51
+ // pipeline operators
52
+ case 'html-template.ng.expression.operator.logical':
53
+ return 'operator.logical';
54
+ case 'html-template.ng.expression.operator.navigator':
55
+ return 'operator.navigator';
56
+ case 'variable.other.property.ts':
57
+ case 'entity.name.function.pipe.ng':
58
+ return 'function.call.pipe';
59
+ case 'variable.other.object.property.ts':
60
+ return 'variable';
61
+ // angular interpolation
62
+ case 'html-template.ng.interpolation.begin':
63
+ return 'expression.template.begin';
64
+ case 'html-template.ng.interpolation.end':
65
+ return 'expression.template.end';
66
+ }
67
+ };
@@ -0,0 +1,46 @@
1
+ import { simplifyNode } from '../parser/nodeUtils.js';
2
+ function transformRecursive(root) {
3
+ if (!root) {
4
+ return;
5
+ }
6
+ switch (root.type) {
7
+ case 'expr':
8
+ case 'array':
9
+ root.values.forEach((item, i) => {
10
+ if (item.type === 'keyInfo' && item.keyName === undefined) {
11
+ const nodeBefore = simplifyNode(root.values[i - 1]);
12
+ if (nodeBefore.type === 'dict') {
13
+ item.keyName = nodeBefore.value['key'];
14
+ item.namespace = nodeBefore.value['ns'] ?? item.namespace;
15
+ item.defaultValue =
16
+ nodeBefore.value['defaultValue'] ?? item.defaultValue;
17
+ }
18
+ else {
19
+ item.keyName = nodeBefore;
20
+ }
21
+ }
22
+ transformRecursive(item);
23
+ });
24
+ break;
25
+ case 'dict':
26
+ Object.values(root.value).forEach(transformRecursive);
27
+ root.unknown.forEach(transformRecursive);
28
+ break;
29
+ case 'keyInfo':
30
+ transformRecursive(root.defaultValue);
31
+ transformRecursive(root.keyName);
32
+ transformRecursive(root.namespace);
33
+ root.values.forEach(transformRecursive);
34
+ break;
35
+ case 'nsInfo':
36
+ transformRecursive(root.name);
37
+ root.values.forEach(transformRecursive);
38
+ break;
39
+ case 'primitive':
40
+ return;
41
+ }
42
+ }
43
+ export const ngxTreeTransform = (root) => {
44
+ transformRecursive(root);
45
+ return { tree: root, report: { keys: [], warnings: [] } };
46
+ };
@@ -0,0 +1,43 @@
1
+ import { parseTag } from '../../parser/tree/parseTag.js';
2
+ // <div t key="test"></div>
3
+ // ^-----------------^^^^^^
4
+ export const componentWithT = {
5
+ trigger: 'trigger.component.with.t',
6
+ call(context) {
7
+ const { getCurrentLine } = context;
8
+ const line = getCurrentLine();
9
+ context.tokens.next();
10
+ const { props, child } = parseTag(context);
11
+ if (props.type !== 'dict' || !props.value['t']) {
12
+ const result = { type: 'array', line, values: [props] };
13
+ if (child) {
14
+ result.values.push(child);
15
+ }
16
+ return result;
17
+ }
18
+ else {
19
+ const result = {
20
+ type: 'keyInfo',
21
+ line,
22
+ dependsOnContext: false,
23
+ values: [],
24
+ };
25
+ for (const [key, value] of Object.entries(props.value)) {
26
+ switch (key) {
27
+ case 'key':
28
+ result.keyName = value;
29
+ break;
30
+ case 'default':
31
+ result.defaultValue = value;
32
+ break;
33
+ case 'ns':
34
+ result.namespace = value;
35
+ break;
36
+ default:
37
+ result.values.push(value);
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ },
43
+ };
@@ -0,0 +1,26 @@
1
+ import { parseGeneral } from '../../../../extractor/parser/tree/parseGeneral.js';
2
+ /*
3
+ * :{ noWrap: true }:'item'
4
+ * ^----------------------^
5
+ */
6
+ export function parsePipeArgs(context, end) {
7
+ const { tokens, getCurrentLine } = context;
8
+ const line = getCurrentLine();
9
+ const result = { type: 'array', line, values: [] };
10
+ let token;
11
+ while ((token = tokens.current())) {
12
+ if (end.includes(token.customType)) {
13
+ break;
14
+ }
15
+ switch (token.customType) {
16
+ case 'operator.navigator':
17
+ tokens.next();
18
+ break;
19
+ default:
20
+ result.values.push(parseGeneral(context, {
21
+ end: ['operator.navigator', ...end],
22
+ }));
23
+ }
24
+ }
25
+ return result;
26
+ }
@@ -0,0 +1,7 @@
1
+ import { tFunctionGeneral } from '../../parser/rules/tFunctionGeneral.js';
2
+ export const translateFunction = {
3
+ trigger: 'trigger.translate.function',
4
+ call(context) {
5
+ return tFunctionGeneral(context, false);
6
+ },
7
+ };
@@ -0,0 +1,57 @@
1
+ import { isString } from '../../../extractor/parser/nodeUtils.js';
2
+ import { parsePipeArgs } from './helpers/parsePipeArgs.js';
3
+ // <div title={{'test' | translate:{noWrap: true}:'default value'}}></div>
4
+ // ^^^^^^^^^^^----------------^^^^^^^^^^^^^^^
5
+ export const translatePipe = {
6
+ trigger: 'trigger.translate.pipe',
7
+ call(context) {
8
+ const { tokens, getCurrentLine } = context;
9
+ const line = getCurrentLine();
10
+ tokens.next();
11
+ const args = parsePipeArgs(context, [
12
+ 'operator.logical',
13
+ 'expression.template.end',
14
+ 'expression.end',
15
+ 'tag.regular.end',
16
+ 'tag.self-closing.end',
17
+ 'tag.attribute.name',
18
+ ]);
19
+ const keyNode = {
20
+ type: 'keyInfo',
21
+ line,
22
+ keyName: undefined,
23
+ dependsOnContext: false,
24
+ values: [],
25
+ };
26
+ let options = undefined;
27
+ if (args.values.length === 1) {
28
+ if (isString(args.values[0])) {
29
+ keyNode.defaultValue = args.values[0];
30
+ }
31
+ else {
32
+ options = args.values[0];
33
+ }
34
+ }
35
+ else if (args.values.length > 1) {
36
+ options = args.values.shift();
37
+ keyNode.defaultValue = args.values.shift();
38
+ keyNode.values = args.values;
39
+ }
40
+ if (options?.type === 'dict') {
41
+ for (const [key, value] of Object.entries(options.value)) {
42
+ switch (key) {
43
+ case 'ns':
44
+ keyNode.namespace = value;
45
+ break;
46
+ default:
47
+ // unknown parameter
48
+ keyNode.values.push(value);
49
+ }
50
+ }
51
+ }
52
+ else if (options) {
53
+ keyNode.optionsDynamic = true;
54
+ }
55
+ return keyNode;
56
+ },
57
+ };
@@ -0,0 +1,29 @@
1
+ // <div ... t
2
+ export const componentWithTMerger = {
3
+ initial: 0 /* S.Idle */,
4
+ step: (state, t, end) => {
5
+ const type = t.customType;
6
+ switch (state) {
7
+ case 0 /* S.Idle */:
8
+ if (type === 'tag.regular.begin') {
9
+ return 1 /* S.ExpectName */;
10
+ }
11
+ break;
12
+ case 1 /* S.ExpectName */:
13
+ if (type === 'tag.name') {
14
+ return 2 /* S.ExpectTParam */;
15
+ }
16
+ break;
17
+ case 2 /* S.ExpectTParam */:
18
+ if (type === 'tag.attribute.name' && t.token === 't') {
19
+ return end.REPLACE_FIRST;
20
+ }
21
+ else if (type === 'tag.self-closing.end' ||
22
+ type === 'tag.regular.end') {
23
+ return undefined;
24
+ }
25
+ return 2 /* S.ExpectTParam */;
26
+ }
27
+ },
28
+ customType: 'trigger.component.with.t',
29
+ };
@@ -0,0 +1,19 @@
1
+ // <div ... t
2
+ export const pipeMerger = {
3
+ initial: 0 /* S.Idle */,
4
+ step: (state, t, end) => {
5
+ const type = t.customType;
6
+ switch (state) {
7
+ case 0 /* S.Idle */:
8
+ if (type === 'operator.logical') {
9
+ return 1 /* S.ExpectTranslate */;
10
+ }
11
+ break;
12
+ case 1 /* S.ExpectTranslate */:
13
+ if (type === 'function.call.pipe' && t.token === 'translate') {
14
+ return end.MERGE_ALL;
15
+ }
16
+ }
17
+ },
18
+ customType: 'trigger.translate.pipe',
19
+ };