chrono-node 2.7.3 → 2.7.5

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 (139) hide show
  1. package/dist/cjs/common/refiners/OverlapRemovalRefiner.js +16 -6
  2. package/dist/cjs/common/refiners/OverlapRemovalRefiner.js.map +1 -1
  3. package/dist/cjs/index.d.ts +1 -1
  4. package/dist/cjs/locales/de/index.d.ts +2 -2
  5. package/dist/cjs/locales/de/index.js.map +1 -1
  6. package/dist/cjs/locales/en/configuration.js +13 -8
  7. package/dist/cjs/locales/en/configuration.js.map +1 -1
  8. package/dist/cjs/locales/en/constants.d.ts +1 -1
  9. package/dist/cjs/locales/en/constants.js +4 -3
  10. package/dist/cjs/locales/en/constants.js.map +1 -1
  11. package/dist/cjs/locales/en/index.d.ts +4 -2
  12. package/dist/cjs/locales/en/index.js +5 -5
  13. package/dist/cjs/locales/en/index.js.map +1 -1
  14. package/dist/cjs/locales/en/parsers/ENMonthNameMiddleEndianParser.d.ts +2 -0
  15. package/dist/cjs/locales/en/parsers/ENMonthNameMiddleEndianParser.js +14 -3
  16. package/dist/cjs/locales/en/parsers/ENMonthNameMiddleEndianParser.js.map +1 -1
  17. package/dist/cjs/locales/en/parsers/ENMonthNameParser.js +1 -0
  18. package/dist/cjs/locales/en/parsers/ENMonthNameParser.js.map +1 -1
  19. package/dist/cjs/locales/en/parsers/ENTimeUnitLaterFormatParser.js +1 -1
  20. package/dist/cjs/locales/en/parsers/ENTimeUnitLaterFormatParser.js.map +1 -1
  21. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -0
  22. package/dist/cjs/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  23. package/dist/cjs/locales/en/refiners/ENMergeRelativeAfterDateRefiner.d.ts +6 -0
  24. package/dist/cjs/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js +30 -0
  25. package/dist/cjs/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js.map +1 -0
  26. package/dist/cjs/locales/en/refiners/{ENMergeRelativeDateRefiner.d.ts → ENMergeRelativeFollowByDateRefiner.d.ts} +1 -1
  27. package/dist/cjs/locales/en/refiners/{ENMergeRelativeDateRefiner.js → ENMergeRelativeFollowByDateRefiner.js} +3 -3
  28. package/dist/cjs/locales/en/refiners/ENMergeRelativeFollowByDateRefiner.js.map +1 -0
  29. package/dist/cjs/locales/es/index.d.ts +2 -2
  30. package/dist/cjs/locales/es/index.js.map +1 -1
  31. package/dist/cjs/locales/fr/index.d.ts +2 -2
  32. package/dist/cjs/locales/fr/index.js.map +1 -1
  33. package/dist/cjs/locales/ja/index.d.ts +2 -2
  34. package/dist/cjs/locales/ja/index.js.map +1 -1
  35. package/dist/cjs/locales/nl/index.d.ts +2 -2
  36. package/dist/cjs/locales/nl/index.js.map +1 -1
  37. package/dist/cjs/locales/nl/parsers/NLRelativeDateFormatParser.js +3 -3
  38. package/dist/cjs/locales/nl/parsers/NLRelativeDateFormatParser.js.map +1 -1
  39. package/dist/cjs/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js +6 -4
  40. package/dist/cjs/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js.map +1 -1
  41. package/dist/cjs/locales/pt/index.d.ts +2 -2
  42. package/dist/cjs/locales/pt/index.js.map +1 -1
  43. package/dist/cjs/locales/ru/index.d.ts +2 -2
  44. package/dist/cjs/locales/ru/index.js.map +1 -1
  45. package/dist/cjs/locales/uk/index.d.ts +2 -2
  46. package/dist/cjs/locales/uk/index.js.map +1 -1
  47. package/dist/cjs/locales/zh/hans/index.d.ts +2 -2
  48. package/dist/cjs/locales/zh/hans/index.js.map +1 -1
  49. package/dist/cjs/locales/zh/hant/index.d.ts +2 -2
  50. package/dist/cjs/locales/zh/hant/index.js.map +1 -1
  51. package/dist/cjs/utils/pattern.d.ts +1 -1
  52. package/dist/cjs/utils/pattern.js +2 -2
  53. package/dist/cjs/utils/pattern.js.map +1 -1
  54. package/dist/esm/common/refiners/OverlapRemovalRefiner.js +16 -6
  55. package/dist/esm/common/refiners/OverlapRemovalRefiner.js.map +1 -1
  56. package/dist/esm/index.d.ts +1 -1
  57. package/dist/esm/locales/de/index.d.ts +2 -2
  58. package/dist/esm/locales/de/index.js.map +1 -1
  59. package/dist/esm/locales/en/configuration.js +13 -8
  60. package/dist/esm/locales/en/configuration.js.map +1 -1
  61. package/dist/esm/locales/en/constants.d.ts +1 -1
  62. package/dist/esm/locales/en/constants.js +4 -3
  63. package/dist/esm/locales/en/constants.js.map +1 -1
  64. package/dist/esm/locales/en/index.d.ts +4 -2
  65. package/dist/esm/locales/en/index.js +4 -4
  66. package/dist/esm/locales/en/index.js.map +1 -1
  67. package/dist/esm/locales/en/parsers/ENMonthNameMiddleEndianParser.d.ts +2 -0
  68. package/dist/esm/locales/en/parsers/ENMonthNameMiddleEndianParser.js +14 -3
  69. package/dist/esm/locales/en/parsers/ENMonthNameMiddleEndianParser.js.map +1 -1
  70. package/dist/esm/locales/en/parsers/ENMonthNameParser.js +1 -0
  71. package/dist/esm/locales/en/parsers/ENMonthNameParser.js.map +1 -1
  72. package/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js +1 -1
  73. package/dist/esm/locales/en/parsers/ENTimeUnitLaterFormatParser.js.map +1 -1
  74. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js +3 -0
  75. package/dist/esm/locales/en/parsers/ENTimeUnitWithinFormatParser.js.map +1 -1
  76. package/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.d.ts +6 -0
  77. package/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js +27 -0
  78. package/dist/esm/locales/en/refiners/ENMergeRelativeAfterDateRefiner.js.map +1 -0
  79. package/dist/esm/locales/en/refiners/{ENMergeRelativeDateRefiner.d.ts → ENMergeRelativeFollowByDateRefiner.d.ts} +1 -1
  80. package/dist/esm/locales/en/refiners/{ENMergeRelativeDateRefiner.js → ENMergeRelativeFollowByDateRefiner.js} +2 -2
  81. package/dist/esm/locales/en/refiners/ENMergeRelativeFollowByDateRefiner.js.map +1 -0
  82. package/dist/esm/locales/es/index.d.ts +2 -2
  83. package/dist/esm/locales/es/index.js.map +1 -1
  84. package/dist/esm/locales/fr/index.d.ts +2 -2
  85. package/dist/esm/locales/fr/index.js.map +1 -1
  86. package/dist/esm/locales/ja/index.d.ts +2 -2
  87. package/dist/esm/locales/ja/index.js.map +1 -1
  88. package/dist/esm/locales/nl/index.d.ts +2 -2
  89. package/dist/esm/locales/nl/index.js.map +1 -1
  90. package/dist/esm/locales/nl/parsers/NLRelativeDateFormatParser.js +3 -3
  91. package/dist/esm/locales/nl/parsers/NLRelativeDateFormatParser.js.map +1 -1
  92. package/dist/esm/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js +6 -4
  93. package/dist/esm/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.js.map +1 -1
  94. package/dist/esm/locales/pt/index.d.ts +2 -2
  95. package/dist/esm/locales/pt/index.js.map +1 -1
  96. package/dist/esm/locales/ru/index.d.ts +2 -2
  97. package/dist/esm/locales/ru/index.js.map +1 -1
  98. package/dist/esm/locales/uk/index.d.ts +2 -2
  99. package/dist/esm/locales/uk/index.js.map +1 -1
  100. package/dist/esm/locales/zh/hans/index.d.ts +2 -2
  101. package/dist/esm/locales/zh/hans/index.js.map +1 -1
  102. package/dist/esm/locales/zh/hant/index.d.ts +2 -2
  103. package/dist/esm/locales/zh/hant/index.js.map +1 -1
  104. package/dist/esm/utils/pattern.d.ts +1 -1
  105. package/dist/esm/utils/pattern.js +2 -2
  106. package/dist/esm/utils/pattern.js.map +1 -1
  107. package/package.json +1 -1
  108. package/src/common/refiners/OverlapRemovalRefiner.ts +16 -7
  109. package/src/index.ts +1 -1
  110. package/src/locales/de/index.ts +2 -2
  111. package/src/locales/en/configuration.ts +15 -8
  112. package/src/locales/en/constants.ts +10 -3
  113. package/src/locales/en/index.ts +6 -6
  114. package/src/locales/en/parsers/ENMonthNameMiddleEndianParser.ts +25 -9
  115. package/src/locales/en/parsers/ENMonthNameParser.ts +1 -0
  116. package/src/locales/en/parsers/ENTimeUnitLaterFormatParser.ts +1 -4
  117. package/src/locales/en/parsers/ENTimeUnitWithinFormatParser.ts +5 -0
  118. package/src/locales/en/refiners/ENMergeRelativeAfterDateRefiner.ts +46 -0
  119. package/src/locales/en/refiners/{ENMergeRelativeDateRefiner.ts → ENMergeRelativeFollowByDateRefiner.ts} +4 -4
  120. package/src/locales/es/index.ts +2 -2
  121. package/src/locales/fr/index.ts +2 -2
  122. package/src/locales/ja/index.ts +2 -2
  123. package/src/locales/nl/index.ts +2 -2
  124. package/src/locales/nl/parsers/NLRelativeDateFormatParser.ts +3 -3
  125. package/src/locales/nl/parsers/NLTimeUnitCasualRelativeFormatParser.ts +10 -4
  126. package/src/locales/pt/index.ts +2 -2
  127. package/src/locales/ru/index.ts +2 -2
  128. package/src/locales/uk/index.ts +2 -2
  129. package/src/locales/zh/hans/index.ts +2 -2
  130. package/src/locales/zh/hant/index.ts +2 -2
  131. package/src/utils/pattern.ts +6 -2
  132. package/test/en/en_month.test.ts +11 -0
  133. package/test/en/en_month_name_middle_endian.test.ts +25 -0
  134. package/test/en/en_time_units_later.test.ts +34 -0
  135. package/test/en/en_time_units_within.test.ts +42 -0
  136. package/test/en/negative_cases.test.ts +4 -0
  137. package/test/nl/nl_relative.test.ts +16 -2
  138. package/dist/cjs/locales/en/refiners/ENMergeRelativeDateRefiner.js.map +0 -1
  139. package/dist/esm/locales/en/refiners/ENMergeRelativeDateRefiner.js.map +0 -1
@@ -6,17 +6,18 @@ import { YEAR_PATTERN, parseYear } from "../constants";
6
6
  import { matchAnyPattern } from "../../../utils/pattern";
7
7
  import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
8
8
 
9
+ // prettier-ignore
9
10
  const PATTERN = new RegExp(
10
11
  `(${matchAnyPattern(MONTH_DICTIONARY)})` +
11
12
  "(?:-|/|\\s*,?\\s*)" +
12
13
  `(${ORDINAL_NUMBER_PATTERN})(?!\\s*(?:am|pm))\\s*` +
13
14
  "(?:" +
14
- "(?:to|\\-)\\s*" +
15
- `(${ORDINAL_NUMBER_PATTERN})\\s*` +
15
+ "(?:to|\\-)\\s*" +
16
+ `(${ORDINAL_NUMBER_PATTERN})\\s*` +
16
17
  ")?" +
17
18
  "(?:" +
18
- "(?:-|/|\\s*,?\\s*)" +
19
- `(${YEAR_PATTERN})` +
19
+ `(?:-|/|\\s*,\\s*|\\s+)` +
20
+ `(${YEAR_PATTERN})` +
20
21
  ")?" +
21
22
  "(?=\\W|$)(?!\\:\\d)",
22
23
  "i"
@@ -36,8 +37,16 @@ const YEAR_GROUP = 4;
36
37
  * - January 12:00
37
38
  * - January 12.44
38
39
  * - January 1222344
40
+ * - January 21 (when shouldSkipYearLikeDate=true)
39
41
  */
40
42
  export default class ENMonthNameMiddleEndianParser extends AbstractParserWithWordBoundaryChecking {
43
+ shouldSkipYearLikeDate: boolean;
44
+
45
+ constructor(shouldSkipYearLikeDate: boolean) {
46
+ super();
47
+ this.shouldSkipYearLikeDate = shouldSkipYearLikeDate;
48
+ }
49
+
41
50
  innerPattern(): RegExp {
42
51
  return PATTERN;
43
52
  }
@@ -49,10 +58,18 @@ export default class ENMonthNameMiddleEndianParser extends AbstractParserWithWor
49
58
  return null;
50
59
  }
51
60
 
52
- const components = context.createParsingComponents({
53
- day: day,
54
- month: month,
55
- });
61
+ // Skip the case where the day looks like a year (ex: January 21)
62
+ if (this.shouldSkipYearLikeDate) {
63
+ if (!match[DATE_TO_GROUP] && !match[YEAR_GROUP] && match[DATE_GROUP].match(/^2[0-5]$/)) {
64
+ return null;
65
+ }
66
+ }
67
+ const components = context
68
+ .createParsingComponents({
69
+ day: day,
70
+ month: month,
71
+ })
72
+ .addTag("parser/ENMonthNameMiddleEndianParser");
56
73
 
57
74
  if (match[YEAR_GROUP]) {
58
75
  const year = parseYear(match[YEAR_GROUP]);
@@ -61,7 +78,6 @@ export default class ENMonthNameMiddleEndianParser extends AbstractParserWithWor
61
78
  const year = findYearClosestToRef(context.refDate, day, month);
62
79
  components.imply("year", year);
63
80
  }
64
-
65
81
  if (!match[DATE_TO_GROUP]) {
66
82
  return components;
67
83
  }
@@ -45,6 +45,7 @@ export default class ENMonthNameParser extends AbstractParserWithWordBoundaryChe
45
45
  match.index + match[0].length
46
46
  );
47
47
  result.start.imply("day", 1);
48
+ result.start.addTag("parser/ENMonthNameParser");
48
49
 
49
50
  const month = MONTH_DICTIONARY[monthName];
50
51
  result.start.assign("month", month);
@@ -8,10 +8,7 @@ const PATTERN = new RegExp(
8
8
  "i"
9
9
  );
10
10
 
11
- const STRICT_PATTERN = new RegExp(
12
- "" + "(" + TIME_UNITS_NO_ABBR_PATTERN + ")" + "(later|from now)" + "(?=(?:\\W|$))",
13
- "i"
14
- );
11
+ const STRICT_PATTERN = new RegExp(`(${TIME_UNITS_NO_ABBR_PATTERN})\\s{0,5}(later|after|from now)(?=\\W|$)`, "i");
15
12
  const GROUP_NUM_TIMEUNITS = 1;
16
13
 
17
14
  export default class ENTimeUnitLaterFormatParser extends AbstractParserWithWordBoundaryChecking {
@@ -34,6 +34,11 @@ export default class ENTimeUnitWithinFormatParser extends AbstractParserWithWord
34
34
  }
35
35
 
36
36
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
37
+ // Exclude "for the unit" phases, e.g. "for the year"
38
+ if (match[0].match(/^for\s*the\s*\w+/)) {
39
+ return null;
40
+ }
41
+
37
42
  const timeUnits = parseTimeUnits(match[1]);
38
43
  return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
39
44
  }
@@ -0,0 +1,46 @@
1
+ import { MergingRefiner } from "../../../common/abstractRefiners";
2
+ import { ParsingComponents, ParsingResult, ReferenceWithTimezone } from "../../../results";
3
+ import { parseTimeUnits } from "../constants";
4
+ import { reverseTimeUnits } from "../../../utils/timeunits";
5
+
6
+ function IsPositiveFollowingReference(result: ParsingResult): boolean {
7
+ return result.text.match(/^[+-]/i) != null;
8
+ }
9
+
10
+ function IsNegativeFollowingReference(result: ParsingResult): boolean {
11
+ return result.text.match(/^-/i) != null;
12
+ }
13
+
14
+ /**
15
+ * Merges a relative data/time that comes after an absolute date.
16
+ * - [2020-02-13] [+2 weeks]
17
+ * - [next tuesday] [+10 days]
18
+ */
19
+ export default class ENMergeRelativeAfterDateRefiner extends MergingRefiner {
20
+ shouldMergeResults(textBetween: string, currentResult: ParsingResult, nextResult: ParsingResult): boolean {
21
+ if (!textBetween.match(/^\s*$/i)) {
22
+ return false;
23
+ }
24
+
25
+ return IsPositiveFollowingReference(nextResult) || IsNegativeFollowingReference(nextResult);
26
+ }
27
+
28
+ mergeResults(textBetween: string, currentResult: ParsingResult, nextResult: ParsingResult, context): ParsingResult {
29
+ let timeUnits = parseTimeUnits(nextResult.text);
30
+ if (IsNegativeFollowingReference(nextResult)) {
31
+ timeUnits = reverseTimeUnits(timeUnits);
32
+ }
33
+
34
+ const components = ParsingComponents.createRelativeFromReference(
35
+ new ReferenceWithTimezone(currentResult.start.date()),
36
+ timeUnits
37
+ );
38
+
39
+ return new ParsingResult(
40
+ currentResult.reference,
41
+ currentResult.index,
42
+ `${currentResult.text}${textBetween}${nextResult.text}`,
43
+ components
44
+ );
45
+ }
46
+ }
@@ -12,11 +12,11 @@ function hasImpliedLaterReferenceDate(result: ParsingResult): boolean {
12
12
  }
13
13
 
14
14
  /**
15
- * Merges an absolute date with a relative date.
16
- * - 2 weeks before 2020-02-13
17
- * - 2 days after next Friday
15
+ * Merges a relative data/time that follow by an absolute date.
16
+ * - [2 weeks before] [2020-02-13]
17
+ * - [2 days after] [next Friday]
18
18
  */
19
- export default class ENMergeRelativeDateRefiner extends MergingRefiner {
19
+ export default class ENMergeRelativeFollowByDateRefiner extends MergingRefiner {
20
20
  patternBetween(): RegExp {
21
21
  return /^\s*$/i;
22
22
  }
@@ -25,11 +25,11 @@ export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Wee
25
25
  export const casual = new Chrono(createCasualConfiguration());
26
26
  export const strict = new Chrono(createConfiguration(true));
27
27
 
28
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
28
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
29
29
  return casual.parse(text, ref, option);
30
30
  }
31
31
 
32
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
32
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
33
33
  return casual.parseDate(text, ref, option);
34
34
  }
35
35
 
@@ -28,11 +28,11 @@ export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Wee
28
28
  export const casual = new Chrono(createCasualConfiguration());
29
29
  export const strict = new Chrono(createConfiguration(true));
30
30
 
31
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
31
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
32
32
  return casual.parse(text, ref, option);
33
33
  }
34
34
 
35
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
35
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
36
36
  return casual.parseDate(text, ref, option);
37
37
  }
38
38
 
@@ -19,11 +19,11 @@ export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Wee
19
19
  export const casual = new Chrono(createCasualConfiguration());
20
20
  export const strict = new Chrono(createConfiguration());
21
21
 
22
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
22
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
23
23
  return casual.parse(text, ref, option);
24
24
  }
25
25
 
26
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
26
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
27
27
  return casual.parseDate(text, ref, option);
28
28
  }
29
29
 
@@ -33,11 +33,11 @@ export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Wee
33
33
  export const casual = new Chrono(createCasualConfiguration());
34
34
  export const strict = new Chrono(createConfiguration(true));
35
35
 
36
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
36
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
37
37
  return casual.parse(text, ref, option);
38
38
  }
39
39
 
40
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
40
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
41
41
  return casual.parseDate(text, ref, option);
42
42
  }
43
43
 
@@ -6,7 +6,7 @@ import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/
6
6
  import { matchAnyPattern } from "../../../utils/pattern";
7
7
 
8
8
  const PATTERN = new RegExp(
9
- `(dit|deze|komende|volgend|volgende|afgelopen|vorige)\\s*(${matchAnyPattern(TIME_UNIT_DICTIONARY)})(?=\\s*)` +
9
+ `(dit|deze|(?:aan)?komend|volgend|afgelopen|vorig)e?\\s*(${matchAnyPattern(TIME_UNIT_DICTIONARY)})(?=\\s*)` +
10
10
  "(?=\\W|$)",
11
11
  "i"
12
12
  );
@@ -24,13 +24,13 @@ export default class NLRelativeDateFormatParser extends AbstractParserWithWordBo
24
24
  const unitWord = match[RELATIVE_WORD_GROUP].toLowerCase();
25
25
  const timeunit = TIME_UNIT_DICTIONARY[unitWord];
26
26
 
27
- if (modifier == "volgend" || modifier == "volgende" || modifier == "komende") {
27
+ if (modifier == "volgend" || modifier == "komend" || modifier == "aankomend") {
28
28
  const timeUnits = {};
29
29
  timeUnits[timeunit] = 1;
30
30
  return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
31
31
  }
32
32
 
33
- if (modifier == "afgelopen" || modifier == "vorige") {
33
+ if (modifier == "afgelopen" || modifier == "vorig") {
34
34
  const timeUnits = {};
35
35
  timeUnits[timeunit] = -1;
36
36
  return ParsingComponents.createRelativeFromReference(context.reference, timeUnits);
@@ -4,7 +4,13 @@ import { ParsingComponents } from "../../../results";
4
4
  import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary";
5
5
  import { reverseTimeUnits } from "../../../utils/timeunits";
6
6
 
7
- const PATTERN = new RegExp(`(deze|vorige|afgelopen|komende|over|\\+|-)\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`, "i");
7
+ const PATTERN = new RegExp(
8
+ `(dit|deze|vorig|afgelopen|(?:aan)?komend|over|\\+|-)e?\\s*(${TIME_UNITS_PATTERN})(?=\\W|$)`,
9
+ "i"
10
+ );
11
+
12
+ const PREFIX_WORD_GROUP = 1;
13
+ const TIME_UNIT_WORD_GROUP = 2;
8
14
 
9
15
  export default class NLTimeUnitCasualRelativeFormatParser extends AbstractParserWithWordBoundaryChecking {
10
16
  innerPattern(): RegExp {
@@ -12,10 +18,10 @@ export default class NLTimeUnitCasualRelativeFormatParser extends AbstractParser
12
18
  }
13
19
 
14
20
  innerExtract(context: ParsingContext, match: RegExpMatchArray): ParsingComponents {
15
- const prefix = match[1].toLowerCase();
16
- let timeUnits = parseTimeUnits(match[2]);
21
+ const prefix = match[PREFIX_WORD_GROUP].toLowerCase();
22
+ let timeUnits = parseTimeUnits(match[TIME_UNIT_WORD_GROUP]);
17
23
  switch (prefix) {
18
- case "vorige":
24
+ case "vorig":
19
25
  case "afgelopen":
20
26
  case "-":
21
27
  timeUnits = reverseTimeUnits(timeUnits);
@@ -24,11 +24,11 @@ export { Component, ParsedResult, ParsingOption, ParsingReference, Meridiem, Wee
24
24
  export const casual = new Chrono(createCasualConfiguration());
25
25
  export const strict = new Chrono(createConfiguration(true));
26
26
 
27
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
27
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
28
28
  return casual.parse(text, ref, option);
29
29
  }
30
30
 
31
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
31
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
32
32
  return casual.parseDate(text, ref, option);
33
33
  }
34
34
 
@@ -40,14 +40,14 @@ export const strict = new Chrono(createConfiguration(true));
40
40
  /**
41
41
  * A shortcut for ru.casual.parse()
42
42
  */
43
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
43
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
44
44
  return casual.parse(text, ref, option);
45
45
  }
46
46
 
47
47
  /**
48
48
  * A shortcut for ru.casual.parseDate()
49
49
  */
50
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
50
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
51
51
  return casual.parseDate(text, ref, option);
52
52
  }
53
53
 
@@ -78,13 +78,13 @@ export function createConfiguration(strictMode: boolean): Configuration {
78
78
  /**
79
79
  * A shortcut for uk.casual.parse()
80
80
  */
81
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
81
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
82
82
  return casual.parse(text, ref, option);
83
83
  }
84
84
 
85
85
  /**
86
86
  * A shortcut for uk.casual.parseDate()
87
87
  */
88
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
88
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
89
89
  return casual.parseDate(text, ref, option);
90
90
  }
@@ -25,11 +25,11 @@ export const hans = new Chrono(createCasualConfiguration());
25
25
  export const casual = new Chrono(createCasualConfiguration());
26
26
  export const strict = new Chrono(createConfiguration());
27
27
 
28
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
28
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
29
29
  return casual.parse(text, ref, option);
30
30
  }
31
31
 
32
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
32
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
33
33
  return casual.parseDate(text, ref, option);
34
34
  }
35
35
 
@@ -26,11 +26,11 @@ export const hant = new Chrono(createCasualConfiguration());
26
26
  export const casual = new Chrono(createCasualConfiguration());
27
27
  export const strict = new Chrono(createConfiguration());
28
28
 
29
- export function parse(text: string, ref?: Date, option?: ParsingOption): ParsedResult[] {
29
+ export function parse(text: string, ref?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
30
30
  return casual.parse(text, ref, option);
31
31
  }
32
32
 
33
- export function parseDate(text: string, ref?: Date, option?: ParsingOption): Date {
33
+ export function parseDate(text: string, ref?: ParsingReference | Date, option?: ParsingOption): Date {
34
34
  return casual.parseDate(text, ref, option);
35
35
  }
36
36
 
@@ -1,8 +1,12 @@
1
1
  type DictionaryLike = string[] | { [word: string]: unknown } | Map<string, unknown>;
2
2
 
3
- export function repeatedTimeunitPattern(prefix: string, singleTimeunitPattern: string): string {
3
+ export function repeatedTimeunitPattern(
4
+ prefix: string,
5
+ singleTimeunitPattern: string,
6
+ connectorPattern = "\\s{0,5},?\\s{0,5}"
7
+ ): string {
4
8
  const singleTimeunitPatternNoCapture = singleTimeunitPattern.replace(/\((?!\?)/g, "(?:");
5
- return `${prefix}${singleTimeunitPatternNoCapture}\\s{0,5}(?:,?\\s{0,5}${singleTimeunitPatternNoCapture}){0,10}`;
9
+ return `${prefix}${singleTimeunitPatternNoCapture}(?:${connectorPattern}${singleTimeunitPatternNoCapture}){0,10}`;
6
10
  }
7
11
 
8
12
  export function extractTerms(dictionary: DictionaryLike): string[] {
@@ -68,6 +68,17 @@ test("Test - Month-Year expression", function () {
68
68
 
69
69
  expect(result.start).toBeDate(new Date(2012, 9 - 1, 1, 12));
70
70
  });
71
+
72
+ testSingleCase(chrono, "Statement of comprehensive income for the year ended Dec. 2021", (result) => {
73
+ expect(result.text).toBe("Dec. 2021");
74
+
75
+ expect(result.start.get("year")).toBe(2021);
76
+ expect(result.start.get("month")).toBe(12);
77
+
78
+ expect(result.start.isCertain("year")).toBe(true);
79
+ expect(result.start.isCertain("month")).toBe(true);
80
+ expect(result.start.isCertain("day")).toBe(false);
81
+ });
71
82
  });
72
83
 
73
84
  test("Test - Month-Only expression", function () {
@@ -1,5 +1,6 @@
1
1
  import * as chrono from "../../src";
2
2
  import { testSingleCase, testWithExpectedDate, testUnexpectedResult } from "../test_util";
3
+ import { configuration } from "../../src/locales/en";
3
4
 
4
5
  test("Test - Single Expression", () => {
5
6
  testSingleCase(chrono, "She is getting married soon (July 2017).", (result) => {
@@ -153,6 +154,13 @@ test("Test - Single Expression", () => {
153
154
  expect(result.start.get("month")).toBe(1);
154
155
  expect(result.start.get("day")).toBe(20);
155
156
  });
157
+
158
+ testSingleCase(chrono, "Dec. 21", new Date(2012, 7, 10), (result) => {
159
+ expect(result.text).toBe("Dec. 21");
160
+ expect(result.start.get("year")).toBe(2012);
161
+ expect(result.start.get("month")).toBe(12);
162
+ expect(result.start.get("day")).toBe(21);
163
+ });
156
164
  });
157
165
 
158
166
  test("Test - Single expression with separators", () => {
@@ -350,6 +358,21 @@ test("Test - year 90's parsing", () => {
350
358
  });
351
359
  });
352
360
 
361
+ test("Test - Skip year-like on little-endian configuration", () => {
362
+ const chronoMiddleEndian = new chrono.Chrono(chrono.en.configuration.createCasualConfiguration(false));
363
+ testSingleCase(chronoMiddleEndian, "Dec. 21", new Date(2023, 12, 10), (result) => {
364
+ expect(result.start.get("year")).toBe(2023);
365
+ expect(result.start.get("month")).toBe(12);
366
+ expect(result.start.get("day")).toBe(21);
367
+ });
368
+
369
+ const chronoLittleEndian = new chrono.Chrono(chrono.en.configuration.createCasualConfiguration(true));
370
+ testSingleCase(chronoLittleEndian, "Dec. 21", new Date(2023, 12, 10), (result) => {
371
+ expect(result.start.get("year")).toBe(2021);
372
+ expect(result.start.get("month")).toBe(12);
373
+ });
374
+ });
375
+
353
376
  test("Test - Impossible Dates (Strict Mode)", () => {
354
377
  testUnexpectedResult(chrono.strict, "August 32, 2014");
355
378
 
@@ -358,4 +381,6 @@ test("Test - Impossible Dates (Strict Mode)", () => {
358
381
  testUnexpectedResult(chrono.strict, "August 32", new Date(2012, 7, 10));
359
382
 
360
383
  testUnexpectedResult(chrono.strict, "February 29", new Date(2014, 7, 10));
384
+
385
+ testUnexpectedResult(chrono.strict, "February 151998", new Date(2014, 7, 10));
361
386
  });
@@ -249,7 +249,9 @@ test("Test - From now Expression", () => {
249
249
 
250
250
  expect(result.start).toBeDate(new Date(2012, 7, 10, 14, 10));
251
251
  });
252
+ });
252
253
 
254
+ test("Test - The later expression with multiple time units", function () {
253
255
  testSingleCase(chrono, "in 1d 2hr 5min", new Date(2012, 7, 10, 12, 40), (result) => {
254
256
  expect(result.index).toBe(0);
255
257
  expect(result.text).toBe("in 1d 2hr 5min");
@@ -259,6 +261,16 @@ test("Test - From now Expression", () => {
259
261
 
260
262
  expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
261
263
  });
264
+
265
+ testSingleCase(chrono, "in 1d, 2hr, and 5min", new Date(2012, 7, 10, 12, 40), (result) => {
266
+ expect(result.index).toBe(0);
267
+ expect(result.text).toBe("in 1d, 2hr, and 5min");
268
+ expect(result.start.get("day")).toBe(11);
269
+ expect(result.start.get("hour")).toBe(14);
270
+ expect(result.start.get("minute")).toBe(45);
271
+
272
+ expect(result.start).toBeDate(new Date(2012, 7, 11, 14, 45));
273
+ });
262
274
  });
263
275
 
264
276
  test("Test - Strict mode", function () {
@@ -320,3 +332,25 @@ test("Test - After with reference", () => {
320
332
  expect(result.start.get("day")).toBe(18);
321
333
  });
322
334
  });
335
+
336
+ test("Test - Plus after reference", () => {
337
+ testSingleCase(chrono, "next tuesday +10 days", new Date(2023, 12 - 1, 29), (result) => {
338
+ expect(result.start.get("year")).toBe(2024);
339
+ expect(result.start.get("month")).toBe(1);
340
+ expect(result.start.get("day")).toBe(12);
341
+ });
342
+
343
+ testSingleCase(chrono, "2023-12-29 -10days", new Date(2023, 12 - 1, 29), (result) => {
344
+ expect(result.start.get("year")).toBe(2023);
345
+ expect(result.start.get("month")).toBe(12);
346
+ expect(result.start.get("day")).toBe(19);
347
+ });
348
+
349
+ testSingleCase(chrono, "now + 40minutes", new Date(2023, 12 - 1, 29, 8, 30), (result) => {
350
+ expect(result.start.get("year")).toBe(2023);
351
+ expect(result.start.get("month")).toBe(12);
352
+ expect(result.start.get("day")).toBe(29);
353
+ expect(result.start.get("hour")).toBe(9);
354
+ expect(result.start.get("minute")).toBe(10);
355
+ });
356
+ });
@@ -174,6 +174,48 @@ test("Test - The normal within expression", () => {
174
174
  });
175
175
  });
176
176
 
177
+ test("Test - The within expression with multiple time units", function () {
178
+ testSingleCase(chrono, "set a timer for 5 minutes 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
179
+ expect(result.index).toBe(12);
180
+ expect(result.text).toBe("for 5 minutes 30 seconds");
181
+
182
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
183
+ });
184
+
185
+ testSingleCase(chrono, "set a timer for 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
186
+ expect(result.index).toBe(12);
187
+ expect(result.text).toBe("for 5 minutes, 30 seconds");
188
+
189
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
190
+ });
191
+
192
+ testSingleCase(chrono, "set a timer for 1 hour, 5 minutes, 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
193
+ expect(result.index).toBe(12);
194
+ expect(result.text).toBe("for 1 hour, 5 minutes, 30 seconds");
195
+
196
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
197
+ });
198
+
199
+ testSingleCase(chrono, "set a timer for 5 minutes and 30 seconds", new Date(2012, 7, 10, 12, 14), (result) => {
200
+ expect(result.index).toBe(12);
201
+ expect(result.text).toBe("for 5 minutes and 30 seconds");
202
+
203
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 12, 19, 30));
204
+ });
205
+
206
+ testSingleCase(
207
+ chrono,
208
+ "set a timer for 1 hour, 5 minutes, and 30 seconds",
209
+ new Date(2012, 7, 10, 12, 14),
210
+ (result) => {
211
+ expect(result.index).toBe(12);
212
+ expect(result.text).toBe("for 1 hour, 5 minutes, and 30 seconds");
213
+
214
+ expect(result.start).toBeDate(new Date(2012, 7, 10, 13, 19, 30));
215
+ }
216
+ );
217
+ });
218
+
177
219
  test("Test - The within expression with certain keywords", () => {
178
220
  testSingleCase(chrono, "In about 5 hours", new Date(2012, 8 - 1, 10, 12, 49), (result, text) => {
179
221
  expect(result.text).toBe(text);
@@ -75,6 +75,10 @@ test("Test - Skip version number pattern", () => {
75
75
  testUnexpectedResult(chrono, "Version: 1.10.30");
76
76
  });
77
77
 
78
+ test("Test - Skip incorrect reference", () => {
79
+ testUnexpectedResult(chrono, "for the year");
80
+ });
81
+
78
82
  test("Test - Date with version number pattern", () => {
79
83
  testSingleCase(chrono.en, "1.5.3 - 2015-09-24", (result) => {
80
84
  expect(result.text).toBe("2015-09-24");
@@ -71,7 +71,7 @@ test("Test - Past relative expressions", () => {
71
71
 
72
72
  test("Test - Future relative expressions", () => {
73
73
  // next hour
74
- testSingleCase(chrono.nl, "komende uur", new Date(2016, 10 - 1, 1, 12), (result, text) => {
74
+ testSingleCase(chrono.nl, "komend uur", new Date(2016, 10 - 1, 1, 12), (result, text) => {
75
75
  expect(result.text).toBe(text);
76
76
  expect(result.start.get("year")).toBe(2016);
77
77
  expect(result.start.get("month")).toBe(10);
@@ -111,6 +111,20 @@ test("Test - Future relative expressions", () => {
111
111
  expect(result.start.isCertain("hour")).toBe(false);
112
112
  });
113
113
 
114
+ // next month
115
+ testSingleCase(chrono.nl, "aankomende maand", new Date(2016, 10 - 1, 1, 12), (result, text) => {
116
+ expect(result.text).toBe(text);
117
+ expect(result.start.get("year")).toBe(2016);
118
+ expect(result.start.get("month")).toBe(11);
119
+ expect(result.start.get("day")).toBe(1);
120
+ expect(result.start.get("hour")).toBe(12);
121
+
122
+ expect(result.start.isCertain("year")).toBe(true);
123
+ expect(result.start.isCertain("month")).toBe(true);
124
+ expect(result.start.isCertain("day")).toBe(false);
125
+ expect(result.start.isCertain("hour")).toBe(false);
126
+ });
127
+
114
128
  // next year
115
129
  testSingleCase(chrono.nl, "volgend jaar", new Date(2020, 11 - 1, 22, 12, 11, 32, 6), (result, text) => {
116
130
  expect(result.text).toBe(text);
@@ -137,7 +151,7 @@ test("Test - Relative date components' certainty", () => {
137
151
  const refDate = new Date(2016, 10 - 1, 7, 12);
138
152
 
139
153
  // next hour
140
- testSingleCase(chrono.nl, "komende uur", refDate, (result, text) => {
154
+ testSingleCase(chrono.nl, "komend uur", refDate, (result, text) => {
141
155
  expect(result.text).toBe(text);
142
156
  expect(result.start.get("year")).toBe(2016);
143
157
  expect(result.start.get("month")).toBe(10);
@@ -1 +0,0 @@
1
- {"version":3,"file":"ENMergeRelativeDateRefiner.js","sourceRoot":"","sources":["../../../../../src/locales/en/refiners/ENMergeRelativeDateRefiner.ts"],"names":[],"mappings":";;AAAA,uEAAkE;AAClE,8CAA2F;AAC3F,4CAA8C;AAC9C,wDAA4D;AAE5D,SAAS,8BAA8B,CAAC,MAAqB;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAED,SAAS,4BAA4B,CAAC,MAAqB;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAOD,MAAqB,0BAA2B,SAAQ,iCAAc;IAClE,cAAc;QACV,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,kBAAkB,CAAC,WAAmB,EAAE,aAA4B,EAAE,UAAyB;QAE3F,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE;YAC3C,OAAO,KAAK,CAAC;SAChB;QAID,IAAI,CAAC,8BAA8B,CAAC,aAAa,CAAC,IAAI,CAAC,4BAA4B,CAAC,aAAa,CAAC,EAAE;YAChG,OAAO,KAAK,CAAC;SAChB;QAGD,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9G,CAAC;IAED,YAAY,CAAC,WAAmB,EAAE,aAA4B,EAAE,UAAyB;QACrF,IAAI,SAAS,GAAG,0BAAc,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,8BAA8B,CAAC,aAAa,CAAC,EAAE;YAC/C,SAAS,GAAG,4BAAgB,CAAC,SAAS,CAAC,CAAC;SAC3C;QAED,MAAM,UAAU,GAAG,2BAAiB,CAAC,2BAA2B,CAC5D,IAAI,+BAAqB,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAClD,SAAS,CACZ,CAAC;QAEF,OAAO,IAAI,uBAAa,CACpB,UAAU,CAAC,SAAS,EACpB,aAAa,CAAC,KAAK,EACnB,GAAG,aAAa,CAAC,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,EACvD,UAAU,CACb,CAAC;IACN,CAAC;CACJ;AAvCD,6CAuCC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ENMergeRelativeDateRefiner.js","sourceRoot":"","sources":["../../../../../src/locales/en/refiners/ENMergeRelativeDateRefiner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,SAAS,8BAA8B,CAAC,MAAqB;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAED,SAAS,4BAA4B,CAAC,MAAqB;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAOD,MAAM,CAAC,OAAO,OAAO,0BAA2B,SAAQ,cAAc;IAClE,cAAc;QACV,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,kBAAkB,CAAC,WAAmB,EAAE,aAA4B,EAAE,UAAyB;QAE3F,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE;YAC3C,OAAO,KAAK,CAAC;SAChB;QAID,IAAI,CAAC,8BAA8B,CAAC,aAAa,CAAC,IAAI,CAAC,4BAA4B,CAAC,aAAa,CAAC,EAAE;YAChG,OAAO,KAAK,CAAC;SAChB;QAGD,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9G,CAAC;IAED,YAAY,CAAC,WAAmB,EAAE,aAA4B,EAAE,UAAyB;QACrF,IAAI,SAAS,GAAG,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,8BAA8B,CAAC,aAAa,CAAC,EAAE;YAC/C,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;SAC3C;QAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,2BAA2B,CAC5D,IAAI,qBAAqB,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAClD,SAAS,CACZ,CAAC;QAEF,OAAO,IAAI,aAAa,CACpB,UAAU,CAAC,SAAS,EACpB,aAAa,CAAC,KAAK,EACnB,GAAG,aAAa,CAAC,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,EACvD,UAAU,CACb,CAAC;IACN,CAAC;CACJ"}