highmark-markdown 0.0.433 → 0.0.435

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 (53) hide show
  1. package/example.js +1634 -919
  2. package/lib/defaultMarkdownStyle.js +2 -2
  3. package/lib/elementMap.js +4 -1
  4. package/lib/example/importer.js +2 -2
  5. package/lib/index/item.js +102 -0
  6. package/lib/index/list.js +88 -0
  7. package/lib/index/match.js +76 -0
  8. package/lib/letters.js +41 -0
  9. package/lib/markdown/bnf.js +2 -2
  10. package/lib/node/markdown/division.js +5 -5
  11. package/lib/node/markdown/footnotesList.js +5 -10
  12. package/lib/node/markdown/indexHeading.js +120 -0
  13. package/lib/node/markdown/indexItem.js +42 -2
  14. package/lib/node/markdown/indexLink.js +2 -3
  15. package/lib/node/markdown/indexList.js +5 -10
  16. package/lib/node/markdown/line.js +2 -2
  17. package/lib/nodeMap.js +3 -2
  18. package/lib/replacement/footnotesList.js +4 -4
  19. package/lib/replacement/index.js +187 -0
  20. package/lib/replacement/indexHeading.js +122 -0
  21. package/lib/replacement/indexItem.js +4 -4
  22. package/lib/replacement/indexList.js +9 -41
  23. package/lib/replacement.js +1 -9
  24. package/lib/ruleNames.js +6 -1
  25. package/lib/utilities/index.js +42 -42
  26. package/lib/utilities/object.js +8 -2
  27. package/package.json +1 -1
  28. package/src/defaultMarkdownStyle.js +18 -1
  29. package/src/elementMap.js +5 -0
  30. package/src/example/importer.js +7 -2
  31. package/src/index/item.js +43 -0
  32. package/src/index/list.js +62 -0
  33. package/src/index/{phraseMatcher.js → match.js} +6 -6
  34. package/src/letters.js +32 -0
  35. package/src/markdown/bnf.js +4 -1
  36. package/src/node/markdown/division.js +4 -4
  37. package/src/node/markdown/footnotesList.js +9 -16
  38. package/src/node/markdown/indexHeading.js +7 -0
  39. package/src/node/markdown/indexItem.js +20 -0
  40. package/src/node/markdown/indexLink.js +1 -4
  41. package/src/node/markdown/indexList.js +9 -16
  42. package/src/node/markdown/line.js +3 -2
  43. package/src/nodeMap.js +4 -1
  44. package/src/replacement/footnotesList.js +4 -3
  45. package/src/replacement/index.js +98 -0
  46. package/src/replacement/indexHeading.js +18 -0
  47. package/src/replacement/indexItem.js +4 -3
  48. package/src/replacement/indexList.js +7 -20
  49. package/src/replacement.js +0 -12
  50. package/src/ruleNames.js +2 -0
  51. package/src/utilities/index.js +46 -46
  52. package/src/utilities/object.js +12 -2
  53. package/lib/index/phraseMatcher.js +0 -76
@@ -6,7 +6,6 @@ import { appendNode,
6
6
  prependNode,
7
7
  removeNode,
8
8
  replaceNode,
9
- replaceNodes,
10
9
  addNodesAfter,
11
10
  appendTokens,
12
11
  prependTokens,
@@ -110,17 +109,6 @@ export default class Replacement {
110
109
  replaceTokens(replacementTokens, replacedNode, tokens);
111
110
  }
112
111
 
113
- replaceEx(replacedNode, parentNode, context) {
114
- const { tokens } = context,
115
- replacementChildNodes = this.getChildNodes(), ///
116
- replacementTokens = this.tokens, ///
117
- replacementNodes = replacementChildNodes; ///
118
-
119
- replaceNodes(replacementNodes, replacedNode, parentNode);
120
-
121
- replaceTokens(replacementTokens, replacedNode, tokens);
122
- }
123
-
124
112
  removeFrom(removedNode, parentNode, context) {
125
113
  const { tokens } = context;
126
114
 
package/src/ruleNames.js CHANGED
@@ -27,6 +27,7 @@ export const INLINE_TEXT_RULE_NAME = "inlineText";
27
27
  export const STRONG_TEXT_RULE_NAME = "strongText";
28
28
  export const SUB_DIVISION_RULE_NAME = "subDivision";
29
29
  export const ORDERED_LIST_RULE_NAME = "orderedList";
30
+ export const INDEX_HEADING_RULE_NAME = "indexHeading";
30
31
  export const BLOCK_LISTING_RULE_NAME = "blockListing";
31
32
  export const CONTENTS_LINK_RULE_NAME = "contentsLink";
32
33
  export const CONTENTS_ITEM_RULE_NAME = "contentsItem";
@@ -88,6 +89,7 @@ const ruleNames = {
88
89
  STRONG_TEXT_RULE_NAME,
89
90
  SUB_DIVISION_RULE_NAME,
90
91
  ORDERED_LIST_RULE_NAME,
92
+ INDEX_HEADING_RULE_NAME,
91
93
  BLOCK_LISTING_RULE_NAME,
92
94
  CONTENTS_LINK_RULE_NAME,
93
95
  CONTENTS_ITEM_RULE_NAME,
@@ -2,10 +2,10 @@
2
2
 
3
3
  import { arrayUtilities } from "necessary";
4
4
 
5
- import PhraseMatcher from "../index/phraseMatcher";
5
+ import IndexMatch from "../index/match";
6
6
 
7
7
  import { EMPTY_STRING, SINGLE_SPACE } from "../constants";
8
- import { forEach, mapValues, mapKeys } from "../utilities/object";
8
+ import { forEach, mapKeys, mapValues } from "../utilities/object";
9
9
 
10
10
  const { compress } = arrayUtilities;
11
11
 
@@ -34,10 +34,10 @@ function createIndexMap(divisionMarkdownNodes, context) {
34
34
 
35
35
  const { indexOptions } = context,
36
36
  { phrases } = indexOptions,
37
- phraseMatchers = phrases.map((phrase) => {
38
- const phraseMatcher = PhraseMatcher.fromPhrase(phrase);
37
+ indexMatches = phrases.map((phrase) => {
38
+ const indexMatch = IndexMatch.fromPhrase(phrase);
39
39
 
40
- return phraseMatcher;
40
+ return indexMatch;
41
41
  });
42
42
 
43
43
  divisionMarkdownNodes.forEach((divisionMarkdownNode) => {
@@ -45,15 +45,15 @@ function createIndexMap(divisionMarkdownNodes, context) {
45
45
 
46
46
  if (pageNumber !== null) {
47
47
  const plainText = divisionMarkdownNode.asPlainText(context),
48
- entries = entriesFromPlainTextAndPhraseMatchers(plainText, phraseMatchers);
48
+ wordsOrPhrases = wordsOrPhrasesFromPlainTextAndIndexMatches(plainText, indexMatches);
49
49
 
50
- entries.forEach((entry) => {
51
- let pageNumbers = indexMap[entry] || null;
50
+ wordsOrPhrases.forEach((wordOrPhrase) => {
51
+ let pageNumbers = indexMap[wordOrPhrase] || null;
52
52
 
53
53
  if (pageNumbers === null) {
54
54
  pageNumbers = [];
55
55
 
56
- indexMap[entry] = pageNumbers;
56
+ indexMap[wordOrPhrase] = pageNumbers;
57
57
  }
58
58
 
59
59
  pageNumbers.push(pageNumber);
@@ -64,28 +64,28 @@ function createIndexMap(divisionMarkdownNodes, context) {
64
64
  return indexMap;
65
65
  }
66
66
 
67
- function entriesFromPlainTextAndPhraseMatchers(plainText, phraseMatchers) {
68
- let entries;
67
+ function wordsOrPhrasesFromPlainTextAndIndexMatches(plainText, indexMatches) {
68
+ let wordsOrPhrases;
69
69
 
70
70
  plainText = preparePlainText(plainText); ///
71
71
 
72
- phraseMatchers.forEach((phraseMatcher) => {
73
- plainText = phraseMatcher.replace(plainText);
72
+ indexMatches.forEach((indexMatch) => {
73
+ plainText = indexMatch.replace(plainText);
74
74
  });
75
75
 
76
- entries = plainText.split(SINGLE_SPACE);
76
+ wordsOrPhrases = plainText.split(SINGLE_SPACE);
77
77
 
78
- entries = entries.map((entry) => {
79
- entry = PhraseMatcher.revert(entry); ///
78
+ wordsOrPhrases = wordsOrPhrases.map((wordOrPhrase) => {
79
+ wordOrPhrase = IndexMatch.revert(wordOrPhrase); ///
80
80
 
81
- return entry;
81
+ return wordOrPhrase;
82
82
  });
83
83
 
84
- return entries;
84
+ return wordsOrPhrases;
85
85
  }
86
86
 
87
87
  function compressPageNumbers(indexMap) {
88
- mapValues(indexMap, (entry, pageNumbers) => {
88
+ mapValues(indexMap, (wordOrPhrase, pageNumbers) => {
89
89
  compress(pageNumbers, (pageNumberA, pageNumberB) => {
90
90
  if (pageNumberA === pageNumberB) {
91
91
  return true;
@@ -117,9 +117,9 @@ function adjustProperNouns(indexMap, context) {
117
117
  return lowerCaseProperNoun;
118
118
  });
119
119
 
120
- mapKeys(indexMap, (entry) => {
120
+ mapKeys(indexMap, (wordOrPhrase) => {
121
121
  const index = lowerCaseProperNouns.findIndex((lowerCaseProperNmae) => {
122
- if (lowerCaseProperNmae === entry) {
122
+ if (lowerCaseProperNmae === wordOrPhrase) {
123
123
  return true;
124
124
  }
125
125
  });
@@ -127,10 +127,10 @@ function adjustProperNouns(indexMap, context) {
127
127
  if (index > -1) {
128
128
  const properNoun = properNouns[index];
129
129
 
130
- entry = properNoun; ///
130
+ wordOrPhrase = properNoun; ///
131
131
  }
132
132
 
133
- return entry;
133
+ return wordOrPhrase;
134
134
  });
135
135
  }
136
136
 
@@ -156,9 +156,9 @@ function adjustAcronyms(indexMap, context) {
156
156
  return lowerCaseAcronym;
157
157
  });
158
158
 
159
- mapKeys(indexMap, (entry) => {
159
+ mapKeys(indexMap, (wordOrPhrase) => {
160
160
  const index = lowerCaseAcronyms.findIndex((lowerCaseProperNmae) => {
161
- if (lowerCaseProperNmae === entry) {
161
+ if (lowerCaseProperNmae === wordOrPhrase) {
162
162
  return true;
163
163
  }
164
164
  });
@@ -166,10 +166,10 @@ function adjustAcronyms(indexMap, context) {
166
166
  if (index > -1) {
167
167
  const acronym = acronyms[index];
168
168
 
169
- entry = acronym; ///
169
+ wordOrPhrase = acronym; ///
170
170
  }
171
171
 
172
- return entry;
172
+ return wordOrPhrase;
173
173
  });
174
174
  }
175
175
 
@@ -178,11 +178,11 @@ function adjustMixedPlurals(indexMap, context) {
178
178
  { plurals } = indexOptions,
179
179
  mixedPlurals = mixedPluralsFromPlurals(plurals);
180
180
 
181
- forEach(indexMap, (entry, pageNumbers) => {
182
- const entryPlural = isPlural(entry);
181
+ forEach(indexMap, (wordOrPhrase, pageNumbers) => {
182
+ const entryPlural = isPlural(wordOrPhrase);
183
183
 
184
184
  if (entryPlural) {
185
- const singularEntry = entry.replace(/s$/, EMPTY_STRING),
185
+ const singularEntry = wordOrPhrase.replace(/s$/, EMPTY_STRING),
186
186
  mixedEntry = `${singularEntry}(s)`,
187
187
  mixedPluralsIncludesMixedEntry = mixedPlurals.includes(mixedEntry),
188
188
  entryMixedPlural = mixedPluralsIncludesMixedEntry; ///
@@ -196,7 +196,7 @@ function adjustMixedPlurals(indexMap, context) {
196
196
  ...singularPageNumbers
197
197
  ];
198
198
 
199
- delete indexMap[entry];
199
+ delete indexMap[wordOrPhrase];
200
200
  delete indexMap[singularEntry];
201
201
 
202
202
  indexMap[mixedEntry] = pageNumbers;
@@ -210,12 +210,12 @@ function adjustPluralPlurals(indexMap, context) {
210
210
  { plurals } = indexOptions,
211
211
  pluralPlurals = pluralPluralsFromPlurals(plurals);
212
212
 
213
- forEach(indexMap, (entry, pageNumbers) => {
214
- const entryPlural = isPlural(entry);
213
+ forEach(indexMap, (wordOrPhrase, pageNumbers) => {
214
+ const entryPlural = isPlural(wordOrPhrase);
215
215
 
216
216
  if (entryPlural) {
217
- const singularEntry = entry.replace(/s$/, EMPTY_STRING),
218
- pluralPluralsIncludesEntry = pluralPlurals.includes(entry),
217
+ const singularEntry = wordOrPhrase.replace(/s$/, EMPTY_STRING),
218
+ pluralPluralsIncludesEntry = pluralPlurals.includes(wordOrPhrase),
219
219
  entryPluralPlural = pluralPluralsIncludesEntry; ///
220
220
 
221
221
  if (entryPluralPlural) {
@@ -229,7 +229,7 @@ function adjustPluralPlurals(indexMap, context) {
229
229
 
230
230
  delete indexMap[singularEntry];
231
231
 
232
- indexMap[entry] = pageNumbers;
232
+ indexMap[wordOrPhrase] = pageNumbers;
233
233
  }
234
234
  }
235
235
  });
@@ -240,11 +240,11 @@ function adjustSingularPlurals(indexMap, context) {
240
240
  { plurals } = indexOptions,
241
241
  singularPlurals = singularPluralsFromPlurals(plurals);
242
242
 
243
- forEach(indexMap, (entry, pageNumbers) => {
244
- const entryPlural = isPlural(entry);
243
+ forEach(indexMap, (wordOrPhrase, pageNumbers) => {
244
+ const entryPlural = isPlural(wordOrPhrase);
245
245
 
246
246
  if (entryPlural) {
247
- const singularEntry = entry.replace(/s$/, EMPTY_STRING),
247
+ const singularEntry = wordOrPhrase.replace(/s$/, EMPTY_STRING),
248
248
  singularPluralsIncludesSingularEntry = singularPlurals.includes(singularEntry),
249
249
  entrySingularPlural = singularPluralsIncludesSingularEntry; ///
250
250
 
@@ -257,7 +257,7 @@ function adjustSingularPlurals(indexMap, context) {
257
257
  ...singularPageNumbers
258
258
  ];
259
259
 
260
- delete indexMap[entry];
260
+ delete indexMap[wordOrPhrase];
261
261
 
262
262
  indexMap[singularEntry] = pageNumbers;
263
263
  }
@@ -314,22 +314,22 @@ function mixedPluralsFromPlurals(plurals) {
314
314
  }
315
315
 
316
316
  function isSingular(text) {
317
- const matches = /[^s)]$/.test(text),
318
- pluralSingular = matches; ///
317
+ const indexMatches = /[^s)]$/.test(text),
318
+ pluralSingular = indexMatches; ///
319
319
 
320
320
  return pluralSingular;
321
321
  }
322
322
 
323
323
  function isPlural(text) {
324
- const matches = /s$/.test(text),
325
- plural = matches; ///
324
+ const indexMatches = /s$/.test(text),
325
+ plural = indexMatches; ///
326
326
 
327
327
  return plural;
328
328
  }
329
329
 
330
330
  function isMixed(text) {
331
- const matches = /\(s\)$/.test(text),
332
- plural = matches; ///
331
+ const indexMatches = /\(s\)$/.test(text),
332
+ plural = indexMatches; ///
333
333
 
334
334
  return plural;
335
335
  }
@@ -24,15 +24,25 @@ export function filter(object, callback) {
24
24
  }
25
25
 
26
26
  export function mapKeys(object, callback) {
27
- const keys = Object.keys(object);
27
+ let keys = Object.keys(object);
28
28
 
29
- keys.forEach((key) => {
29
+ const values = [];
30
+
31
+ keys = keys.map((key) => {
30
32
  const value = object[key];
31
33
 
32
34
  delete object[key];
33
35
 
34
36
  key = callback(key, value); ///
35
37
 
38
+ values.push(value);
39
+
40
+ return key;
41
+ });
42
+
43
+ keys.forEach((key, index) => {
44
+ const value = values[index];
45
+
36
46
  object[key] = value;
37
47
  });
38
48
  }
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "default", {
6
- enumerable: true,
7
- get: function() {
8
- return PhraseMatcher;
9
- }
10
- });
11
- var _constants = require("../constants");
12
- function _class_call_check(instance, Constructor) {
13
- if (!(instance instanceof Constructor)) {
14
- throw new TypeError("Cannot call a class as a function");
15
- }
16
- }
17
- function _defineProperties(target, props) {
18
- for(var i = 0; i < props.length; i++){
19
- var descriptor = props[i];
20
- descriptor.enumerable = descriptor.enumerable || false;
21
- descriptor.configurable = true;
22
- if ("value" in descriptor) descriptor.writable = true;
23
- Object.defineProperty(target, descriptor.key, descriptor);
24
- }
25
- }
26
- function _create_class(Constructor, protoProps, staticProps) {
27
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
28
- if (staticProps) _defineProperties(Constructor, staticProps);
29
- return Constructor;
30
- }
31
- var PhraseMatcher = /*#__PURE__*/ function() {
32
- function PhraseMatcher(regularExpression, replacement) {
33
- _class_call_check(this, PhraseMatcher);
34
- this.regularExpression = regularExpression;
35
- this.replacement = replacement;
36
- }
37
- _create_class(PhraseMatcher, [
38
- {
39
- key: "getRegularExpression",
40
- value: function getRegularExpression() {
41
- return this.regularExpression;
42
- }
43
- },
44
- {
45
- key: "getReplacement",
46
- value: function getReplacement() {
47
- return this.replacement;
48
- }
49
- },
50
- {
51
- key: "replace",
52
- value: function replace(plainText) {
53
- plainText = plainText.replace(this.regularExpression, this.replacement); ///
54
- return plainText;
55
- }
56
- }
57
- ], [
58
- {
59
- key: "revert",
60
- value: function revert(entry) {
61
- entry = entry.replace(/_/g, _constants.SINGLE_SPACE);
62
- return entry;
63
- }
64
- },
65
- {
66
- key: "fromPhrase",
67
- value: function fromPhrase(phrase) {
68
- var regularExpression = new RegExp(phrase, _constants.GLOBAL_FLAG), replacement = phrase.replace(/\s/g, _constants.UNDERSCORE), phraseMatcher = new PhraseMatcher(regularExpression, replacement);
69
- return phraseMatcher;
70
- }
71
- }
72
- ]);
73
- return PhraseMatcher;
74
- }();
75
-
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbmRleC9waHJhc2VNYXRjaGVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgeyBVTkRFUlNDT1JFLCBHTE9CQUxfRkxBRywgU0lOR0xFX1NQQUNFIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQaHJhc2VNYXRjaGVyIHtcbiAgY29uc3RydWN0b3IocmVndWxhckV4cHJlc3Npb24sIHJlcGxhY2VtZW50KSB7XG4gICAgdGhpcy5yZWd1bGFyRXhwcmVzc2lvbiA9IHJlZ3VsYXJFeHByZXNzaW9uO1xuICAgIHRoaXMucmVwbGFjZW1lbnQgPSByZXBsYWNlbWVudDtcbiAgfVxuXG4gIGdldFJlZ3VsYXJFeHByZXNzaW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJlZ3VsYXJFeHByZXNzaW9uO1xuICB9XG5cbiAgZ2V0UmVwbGFjZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZW1lbnQ7XG4gIH1cblxuICByZXBsYWNlKHBsYWluVGV4dCkge1xuICAgIHBsYWluVGV4dCA9IHBsYWluVGV4dC5yZXBsYWNlKHRoaXMucmVndWxhckV4cHJlc3Npb24sIHRoaXMucmVwbGFjZW1lbnQpOyAgLy8vXG5cbiAgICByZXR1cm4gcGxhaW5UZXh0O1xuICB9XG5cbiAgc3RhdGljIHJldmVydChlbnRyeSkge1xuICAgIGVudHJ5ID0gZW50cnkucmVwbGFjZSgvXy9nLCBTSU5HTEVfU1BBQ0UpO1xuXG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cbiAgc3RhdGljIGZyb21QaHJhc2UocGhyYXNlKSB7XG4gICAgY29uc3QgcmVndWxhckV4cHJlc3Npb24gPSBuZXcgUmVnRXhwKHBocmFzZSwgR0xPQkFMX0ZMQUcpLFxuICAgICAgICAgIHJlcGxhY2VtZW50ID0gcGhyYXNlLnJlcGxhY2UoL1xccy9nLCBVTkRFUlNDT1JFKSxcbiAgICAgICAgICBwaHJhc2VNYXRjaGVyID0gbmV3IFBocmFzZU1hdGNoZXIocmVndWxhckV4cHJlc3Npb24sIHJlcGxhY2VtZW50KTtcblxuICAgIHJldHVybiBwaHJhc2VNYXRjaGVyO1xuICB9XG59XG4iXSwibmFtZXMiOlsiUGhyYXNlTWF0Y2hlciIsInJlZ3VsYXJFeHByZXNzaW9uIiwicmVwbGFjZW1lbnQiLCJnZXRSZWd1bGFyRXhwcmVzc2lvbiIsImdldFJlcGxhY2VtZW50IiwicmVwbGFjZSIsInBsYWluVGV4dCIsInJldmVydCIsImVudHJ5IiwiU0lOR0xFX1NQQUNFIiwiZnJvbVBocmFzZSIsInBocmFzZSIsIlJlZ0V4cCIsIkdMT0JBTF9GTEFHIiwiVU5ERVJTQ09SRSIsInBocmFzZU1hdGNoZXIiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O2VBSXFCQTs7O3lCQUZpQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFdkMsSUFBQSxBQUFNQSw4QkFBRCxBQUFMO2FBQU1BLGNBQ1BDLGlCQUFpQixFQUFFQyxXQUFXO2dDQUR2QkY7UUFFakIsSUFBSSxDQUFDQyxpQkFBaUIsR0FBR0E7UUFDekIsSUFBSSxDQUFDQyxXQUFXLEdBQUdBOztrQkFIRkY7O1lBTW5CRyxLQUFBQTttQkFBQUEsU0FBQUE7Z0JBQ0UsT0FBTyxJQUFJLENBQUNGLGlCQUFpQjtZQUMvQjs7O1lBRUFHLEtBQUFBO21CQUFBQSxTQUFBQTtnQkFDRSxPQUFPLElBQUksQ0FBQ0YsV0FBVztZQUN6Qjs7O1lBRUFHLEtBQUFBO21CQUFBQSxTQUFBQSxRQUFRQyxTQUFTO2dCQUNmQSxZQUFZQSxVQUFVRCxPQUFPLENBQUMsSUFBSSxDQUFDSixpQkFBaUIsRUFBRSxJQUFJLENBQUNDLFdBQVcsR0FBSSxHQUFHO2dCQUU3RSxPQUFPSTtZQUNUOzs7O1lBRU9DLEtBQUFBO21CQUFQLFNBQU9BLE9BQU9DLEtBQUs7Z0JBQ2pCQSxRQUFRQSxNQUFNSCxPQUFPLENBQUMsTUFBTUksdUJBQVk7Z0JBRXhDLE9BQU9EO1lBQ1Q7OztZQUVPRSxLQUFBQTttQkFBUCxTQUFPQSxXQUFXQyxNQUFNO2dCQUN0QixJQUFNVixvQkFBb0IsSUFBSVcsT0FBT0QsUUFBUUUsc0JBQVcsR0FDbERYLGNBQWNTLE9BQU9OLE9BQU8sQ0FBQyxPQUFPUyxxQkFBVSxHQUM5Q0MsZ0JBQWdCLElBN0JMZixjQTZCdUJDLG1CQUFtQkM7Z0JBRTNELE9BQU9hO1lBQ1Q7OztXQWhDbUJmIn0=