@trebco/treb 23.6.2 → 25.0.0-rc1

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 (217) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +164 -0
  3. package/README-shadow-DOM.md +88 -0
  4. package/README.md +37 -130
  5. package/api-config.json +29 -0
  6. package/api-generator/api-generator-types.ts +82 -0
  7. package/api-generator/api-generator.ts +1172 -0
  8. package/api-generator/package.json +3 -0
  9. package/build/treb-spreadsheet.mjs +14 -0
  10. package/{treb.d.ts → build/treb.d.ts} +293 -299
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +43 -14
  14. package/treb-base-types/package.json +5 -0
  15. package/treb-base-types/src/api_types.ts +36 -0
  16. package/treb-base-types/src/area.ts +583 -0
  17. package/treb-base-types/src/basic_types.ts +45 -0
  18. package/treb-base-types/src/cell.ts +612 -0
  19. package/treb-base-types/src/cells.ts +1066 -0
  20. package/treb-base-types/src/color.ts +124 -0
  21. package/treb-base-types/src/import.ts +71 -0
  22. package/treb-base-types/src/index-standalone.ts +29 -0
  23. package/treb-base-types/src/index.ts +42 -0
  24. package/treb-base-types/src/layout.ts +47 -0
  25. package/treb-base-types/src/localization.ts +187 -0
  26. package/treb-base-types/src/rectangle.ts +145 -0
  27. package/treb-base-types/src/render_text.ts +72 -0
  28. package/treb-base-types/src/style.ts +545 -0
  29. package/treb-base-types/src/table.ts +109 -0
  30. package/treb-base-types/src/text_part.ts +54 -0
  31. package/treb-base-types/src/theme.ts +608 -0
  32. package/treb-base-types/src/union.ts +152 -0
  33. package/treb-base-types/src/value-type.ts +164 -0
  34. package/treb-base-types/style/resizable.css +59 -0
  35. package/treb-calculator/modern.tsconfig.json +11 -0
  36. package/treb-calculator/package.json +5 -0
  37. package/treb-calculator/src/calculator.ts +2546 -0
  38. package/treb-calculator/src/complex-math.ts +558 -0
  39. package/treb-calculator/src/dag/array-vertex.ts +198 -0
  40. package/treb-calculator/src/dag/graph.ts +951 -0
  41. package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
  42. package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
  43. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
  44. package/treb-calculator/src/dag/vertex.ts +352 -0
  45. package/treb-calculator/src/descriptors.ts +162 -0
  46. package/treb-calculator/src/expression-calculator.ts +1069 -0
  47. package/treb-calculator/src/function-error.ts +103 -0
  48. package/treb-calculator/src/function-library.ts +103 -0
  49. package/treb-calculator/src/functions/base-functions.ts +1214 -0
  50. package/treb-calculator/src/functions/checkbox.ts +164 -0
  51. package/treb-calculator/src/functions/complex-functions.ts +253 -0
  52. package/treb-calculator/src/functions/finance-functions.ts +399 -0
  53. package/treb-calculator/src/functions/information-functions.ts +102 -0
  54. package/treb-calculator/src/functions/matrix-functions.ts +182 -0
  55. package/treb-calculator/src/functions/sparkline.ts +335 -0
  56. package/treb-calculator/src/functions/statistics-functions.ts +350 -0
  57. package/treb-calculator/src/functions/text-functions.ts +298 -0
  58. package/treb-calculator/src/index.ts +27 -0
  59. package/treb-calculator/src/notifier-types.ts +59 -0
  60. package/treb-calculator/src/primitives.ts +428 -0
  61. package/treb-calculator/src/utilities.ts +305 -0
  62. package/treb-charts/package.json +5 -0
  63. package/treb-charts/src/chart-functions.ts +156 -0
  64. package/treb-charts/src/chart-types.ts +230 -0
  65. package/treb-charts/src/chart.ts +1288 -0
  66. package/treb-charts/src/index.ts +24 -0
  67. package/treb-charts/src/main.ts +37 -0
  68. package/treb-charts/src/rectangle.ts +52 -0
  69. package/treb-charts/src/renderer.ts +1841 -0
  70. package/treb-charts/src/util.ts +122 -0
  71. package/treb-charts/style/charts.scss +221 -0
  72. package/treb-charts/style/old-charts.scss +250 -0
  73. package/treb-embed/markup/layout.html +137 -0
  74. package/treb-embed/markup/toolbar.html +175 -0
  75. package/treb-embed/modern.tsconfig.json +25 -0
  76. package/treb-embed/src/custom-element/content-types.d.ts +18 -0
  77. package/treb-embed/src/custom-element/global.d.ts +11 -0
  78. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
  79. package/treb-embed/src/custom-element/treb-global.ts +44 -0
  80. package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
  81. package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
  82. package/treb-embed/src/index.ts +16 -0
  83. package/treb-embed/src/language-model.ts +41 -0
  84. package/treb-embed/src/options.ts +320 -0
  85. package/treb-embed/src/progress-dialog.ts +228 -0
  86. package/treb-embed/src/selection-state.ts +16 -0
  87. package/treb-embed/src/spinner.ts +42 -0
  88. package/treb-embed/src/toolbar-message.ts +96 -0
  89. package/treb-embed/src/types.ts +167 -0
  90. package/treb-embed/style/autocomplete.scss +103 -0
  91. package/treb-embed/style/dark-theme.scss +114 -0
  92. package/treb-embed/style/defaults.scss +36 -0
  93. package/treb-embed/style/dialog.scss +181 -0
  94. package/treb-embed/style/dropdown-select.scss +101 -0
  95. package/treb-embed/style/formula-bar.scss +193 -0
  96. package/treb-embed/style/grid.scss +374 -0
  97. package/treb-embed/style/layout.scss +424 -0
  98. package/treb-embed/style/mouse-mask.scss +67 -0
  99. package/treb-embed/style/note.scss +92 -0
  100. package/treb-embed/style/overlay-editor.scss +102 -0
  101. package/treb-embed/style/spinner.scss +92 -0
  102. package/treb-embed/style/tab-bar.scss +228 -0
  103. package/treb-embed/style/table.scss +80 -0
  104. package/treb-embed/style/theme-defaults.scss +444 -0
  105. package/treb-embed/style/toolbar.scss +416 -0
  106. package/treb-embed/style/tooltip.scss +68 -0
  107. package/treb-embed/style/treb-icons.scss +130 -0
  108. package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
  109. package/treb-embed/style/z-index.scss +43 -0
  110. package/treb-export/docs/charts.md +68 -0
  111. package/treb-export/modern.tsconfig.json +19 -0
  112. package/treb-export/package.json +4 -0
  113. package/treb-export/src/address-type.ts +77 -0
  114. package/treb-export/src/base-template.ts +22 -0
  115. package/treb-export/src/column-width.ts +85 -0
  116. package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
  117. package/treb-export/src/drawing2/chart2.ts +282 -0
  118. package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
  119. package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
  120. package/treb-export/src/drawing2/drawing2.ts +355 -0
  121. package/treb-export/src/drawing2/embedded-image.ts +71 -0
  122. package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
  123. package/treb-export/src/export-worker/export-worker.ts +99 -0
  124. package/treb-export/src/export-worker/index-modern.ts +22 -0
  125. package/treb-export/src/export2.ts +2204 -0
  126. package/treb-export/src/import2.ts +882 -0
  127. package/treb-export/src/relationship.ts +36 -0
  128. package/treb-export/src/shared-strings2.ts +128 -0
  129. package/treb-export/src/template-2.ts +22 -0
  130. package/treb-export/src/unescape_xml.ts +47 -0
  131. package/treb-export/src/workbook-sheet2.ts +182 -0
  132. package/treb-export/src/workbook-style2.ts +1285 -0
  133. package/treb-export/src/workbook-theme2.ts +88 -0
  134. package/treb-export/src/workbook2.ts +491 -0
  135. package/treb-export/src/xml-utils.ts +201 -0
  136. package/treb-export/template/base/[Content_Types].xml +2 -0
  137. package/treb-export/template/base/_rels/.rels +2 -0
  138. package/treb-export/template/base/docProps/app.xml +2 -0
  139. package/treb-export/template/base/docProps/core.xml +12 -0
  140. package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
  141. package/treb-export/template/base/xl/sharedStrings.xml +2 -0
  142. package/treb-export/template/base/xl/styles.xml +2 -0
  143. package/treb-export/template/base/xl/theme/theme1.xml +2 -0
  144. package/treb-export/template/base/xl/workbook.xml +2 -0
  145. package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
  146. package/treb-export/template/base.xlsx +0 -0
  147. package/treb-format/package.json +8 -0
  148. package/treb-format/src/format.test.ts +213 -0
  149. package/treb-format/src/format.ts +942 -0
  150. package/treb-format/src/format_cache.ts +199 -0
  151. package/treb-format/src/format_parser.ts +723 -0
  152. package/treb-format/src/index.ts +25 -0
  153. package/treb-format/src/number_format_section.ts +100 -0
  154. package/treb-format/src/value_parser.ts +337 -0
  155. package/treb-grid/package.json +5 -0
  156. package/treb-grid/src/editors/autocomplete.ts +394 -0
  157. package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
  158. package/treb-grid/src/editors/formula_bar.ts +473 -0
  159. package/treb-grid/src/editors/formula_editor_base.ts +910 -0
  160. package/treb-grid/src/editors/overlay_editor.ts +511 -0
  161. package/treb-grid/src/index.ts +37 -0
  162. package/treb-grid/src/layout/base_layout.ts +2618 -0
  163. package/treb-grid/src/layout/grid_layout.ts +299 -0
  164. package/treb-grid/src/layout/rectangle_cache.ts +86 -0
  165. package/treb-grid/src/render/selection-renderer.ts +414 -0
  166. package/treb-grid/src/render/svg_header_overlay.ts +93 -0
  167. package/treb-grid/src/render/svg_selection_block.ts +187 -0
  168. package/treb-grid/src/render/tile_renderer.ts +2122 -0
  169. package/treb-grid/src/types/annotation.ts +216 -0
  170. package/treb-grid/src/types/border_constants.ts +34 -0
  171. package/treb-grid/src/types/clipboard_data.ts +31 -0
  172. package/treb-grid/src/types/data_model.ts +334 -0
  173. package/treb-grid/src/types/drag_mask.ts +81 -0
  174. package/treb-grid/src/types/grid.ts +7743 -0
  175. package/treb-grid/src/types/grid_base.ts +3644 -0
  176. package/treb-grid/src/types/grid_command.ts +470 -0
  177. package/treb-grid/src/types/grid_events.ts +124 -0
  178. package/treb-grid/src/types/grid_options.ts +97 -0
  179. package/treb-grid/src/types/grid_selection.ts +60 -0
  180. package/treb-grid/src/types/named_range.ts +369 -0
  181. package/treb-grid/src/types/scale-control.ts +202 -0
  182. package/treb-grid/src/types/serialize_options.ts +72 -0
  183. package/treb-grid/src/types/set_range_options.ts +52 -0
  184. package/treb-grid/src/types/sheet.ts +3099 -0
  185. package/treb-grid/src/types/sheet_types.ts +95 -0
  186. package/treb-grid/src/types/tab_bar.ts +464 -0
  187. package/treb-grid/src/types/tile.ts +59 -0
  188. package/treb-grid/src/types/update_flags.ts +75 -0
  189. package/treb-grid/src/util/dom_utilities.ts +44 -0
  190. package/treb-grid/src/util/fontmetrics2.ts +179 -0
  191. package/treb-grid/src/util/ua.ts +104 -0
  192. package/treb-logo.svg +18 -0
  193. package/treb-parser/package.json +5 -0
  194. package/treb-parser/src/csv-parser.ts +122 -0
  195. package/treb-parser/src/index.ts +25 -0
  196. package/treb-parser/src/md-parser.ts +526 -0
  197. package/treb-parser/src/parser-types.ts +397 -0
  198. package/treb-parser/src/parser.test.ts +298 -0
  199. package/treb-parser/src/parser.ts +2673 -0
  200. package/treb-utils/package.json +5 -0
  201. package/treb-utils/src/dispatch.ts +57 -0
  202. package/treb-utils/src/event_source.ts +147 -0
  203. package/treb-utils/src/ievent_source.ts +33 -0
  204. package/treb-utils/src/index.ts +31 -0
  205. package/treb-utils/src/measurement.ts +174 -0
  206. package/treb-utils/src/resizable.ts +160 -0
  207. package/treb-utils/src/scale.ts +137 -0
  208. package/treb-utils/src/serialize_html.ts +124 -0
  209. package/treb-utils/src/template.ts +70 -0
  210. package/treb-utils/src/validate_uri.ts +61 -0
  211. package/tsconfig.json +10 -0
  212. package/tsproject.json +30 -0
  213. package/util/license-plugin-esbuild.js +86 -0
  214. package/util/list-css-vars.sh +46 -0
  215. package/README-esm.md +0 -37
  216. package/treb-bundle.css +0 -2
  217. package/treb-bundle.mjs +0 -15
@@ -0,0 +1,36 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ export interface Relationship {
23
+ id: string,
24
+ type: string,
25
+ target: string,
26
+ mode?: string;
27
+ }
28
+
29
+ export type RelationshipMap = Record<string, Relationship>;
30
+
31
+ export const AddRel = (map: RelationshipMap, type: string, target: string, mode?: string): string => {
32
+ const index = Object.keys(map).length + 1;
33
+ const rel = `rId${index}`;
34
+ map[rel] = { id: rel, type, target, mode };
35
+ return rel;
36
+ };
@@ -0,0 +1,128 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import {XMLUtils} from './xml-utils';
23
+
24
+ export class SharedStrings {
25
+
26
+ public strings: string[] = [];
27
+ public reverse: Record<string, number> = {};
28
+
29
+ /** read strings table from (pre-parsed) xml; removes any existing strings */
30
+ public FromXML(xml: any) {
31
+
32
+ // clear
33
+
34
+ this.strings = [];
35
+ this.reverse = {};
36
+
37
+ let index = 0;
38
+
39
+ for (const si of XMLUtils.FindAll(xml, 'sst/si')) {
40
+
41
+ // simple string looks like
42
+ //
43
+ // <si>
44
+ // <t>text here!</t>
45
+ // </si>
46
+
47
+ if (si.t) {
48
+
49
+ // seen recently in the wild, text with leading (or trailing) spaces
50
+ // has an attribute xml:space=preserve (which makes sense, but was not
51
+ // expecting it)
52
+ //
53
+ // <si>
54
+ // <t xml:space="preserve"> (Target portfolio lease rate based on internal estimate of average Canadian farmland rates)</t>
55
+ // </si>
56
+ //
57
+
58
+ let base = '';
59
+ if (typeof si.t === 'string') { base = si.t; }
60
+ else if (si.t.t$) {
61
+ base = si.t.t$;
62
+ }
63
+
64
+ this.strings[index] = base;
65
+ this.reverse[base] = index;
66
+
67
+ }
68
+
69
+ // complex string looks like
70
+ //
71
+ // <si>
72
+ // <r>
73
+ // <rPr>(...style data...)</rPr>
74
+ // <t>text part</t>
75
+ // </r>
76
+ // </si>
77
+ //
78
+ // where there can be multiple r tags with different styling.
79
+ // since we don't support that atm, let's drop style and just
80
+ // collect text.
81
+
82
+ else if (si.r) {
83
+ const parts = XMLUtils.FindAll(si.r, 't');
84
+
85
+ const composite = parts.map(part => {
86
+ return (typeof part === 'string') ? part : (part.t$ || '');
87
+ }).join('');
88
+
89
+ this.strings[index] = composite;
90
+ this.reverse[composite] = index;
91
+ }
92
+ else {
93
+ console.warn(` ** unexpected shared string @ ${index}`);
94
+ console.info(si);
95
+ }
96
+
97
+ index++;
98
+
99
+ }
100
+
101
+ }
102
+
103
+ /** return a string by index */
104
+ public Get(index: number): string|undefined {
105
+ return this.strings[index];
106
+ }
107
+
108
+ /** find existing string or insert, and return index */
109
+ public Ensure(text: string): number {
110
+
111
+ if (text[0] === '\'') {
112
+ text = text.substring(1);
113
+ }
114
+
115
+ let index = this.reverse[text];
116
+ if (typeof index === 'number') {
117
+ return index;
118
+ }
119
+
120
+ index = this.strings.length;
121
+ this.strings.push(text);
122
+ this.reverse[text] = index;
123
+ return index;
124
+
125
+ }
126
+
127
+
128
+ }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ export const template = 'UEsDBAoAAAAAAAAAIQBi7p1okAQAAJAEAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbDw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4NCjxUeXBlcyB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3BhY2thZ2UvMjAwNi9jb250ZW50LXR5cGVzIj48RGVmYXVsdCBFeHRlbnNpb249InJlbHMiIENvbnRlbnRUeXBlPSJhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtcGFja2FnZS5yZWxhdGlvbnNoaXBzK3htbCIvPjxEZWZhdWx0IEV4dGVuc2lvbj0ieG1sIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24veG1sIi8+PE92ZXJyaWRlIFBhcnROYW1lPSIveGwvd29ya2Jvb2sueG1sIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LnNwcmVhZHNoZWV0bWwuc2hlZXQubWFpbit4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii94bC93b3Jrc2hlZXRzL3NoZWV0MS54bWwiIENvbnRlbnRUeXBlPSJhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC53b3Jrc2hlZXQreG1sIi8+PE92ZXJyaWRlIFBhcnROYW1lPSIveGwvdGhlbWUvdGhlbWUxLnhtbCIgQ29udGVudFR5cGU9ImFwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC50aGVtZSt4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii94bC9zdHlsZXMueG1sIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LnNwcmVhZHNoZWV0bWwuc3R5bGVzK3htbCIvPjxPdmVycmlkZSBQYXJ0TmFtZT0iL3hsL3NoYXJlZFN0cmluZ3MueG1sIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LnNwcmVhZHNoZWV0bWwuc2hhcmVkU3RyaW5ncyt4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii9kb2NQcm9wcy9jb3JlLnhtbCIgQ29udGVudFR5cGU9ImFwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1wYWNrYWdlLmNvcmUtcHJvcGVydGllcyt4bWwiLz48T3ZlcnJpZGUgUGFydE5hbWU9Ii9kb2NQcm9wcy9hcHAueG1sIiBDb250ZW50VHlwZT0iYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LmV4dGVuZGVkLXByb3BlcnRpZXMreG1sIi8+PC9UeXBlcz5QSwMECgAAAAAAAAAhALVVMCNMAgAATAIAAAsAAABfcmVscy8ucmVsczw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4NCjxSZWxhdGlvbnNoaXBzIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvcGFja2FnZS8yMDA2L3JlbGF0aW9uc2hpcHMiPjxSZWxhdGlvbnNoaXAgSWQ9InJJZDMiIFR5cGU9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L3JlbGF0aW9uc2hpcHMvZXh0ZW5kZWQtcHJvcGVydGllcyIgVGFyZ2V0PSJkb2NQcm9wcy9hcHAueG1sIi8+PFJlbGF0aW9uc2hpcCBJZD0icklkMiIgVHlwZT0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3BhY2thZ2UvMjAwNi9yZWxhdGlvbnNoaXBzL21ldGFkYXRhL2NvcmUtcHJvcGVydGllcyIgVGFyZ2V0PSJkb2NQcm9wcy9jb3JlLnhtbCIvPjxSZWxhdGlvbnNoaXAgSWQ9InJJZDEiIFR5cGU9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L3JlbGF0aW9uc2hpcHMvb2ZmaWNlRG9jdW1lbnQiIFRhcmdldD0ieGwvd29ya2Jvb2sueG1sIi8+PC9SZWxhdGlvbnNoaXBzPlBLAwQKAAAAAAAAACEAunCeZsoGAADKBgAADwAAAHhsL3dvcmtib29rLnhtbDw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4NCjx3b3JrYm9vayB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3NwcmVhZHNoZWV0bWwvMjAwNi9tYWluIiB4bWxuczpyPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzIiB4bWxuczptYz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL21hcmt1cC1jb21wYXRpYmlsaXR5LzIwMDYiIG1jOklnbm9yYWJsZT0ieDE1IHhyIHhyNiB4cjEwIHhyMiIgeG1sbnM6eDE1PSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTAvMTEvbWFpbiIgeG1sbnM6eHI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAxNC9yZXZpc2lvbiIgeG1sbnM6eHI2PSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTYvcmV2aXNpb242IiB4bWxuczp4cjEwPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTYvcmV2aXNpb24xMCIgeG1sbnM6eHIyPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTUvcmV2aXNpb24yIj48ZmlsZVZlcnNpb24gYXBwTmFtZT0ieGwiIGxhc3RFZGl0ZWQ9IjciIGxvd2VzdEVkaXRlZD0iNyIgcnVwQnVpbGQ9IjIxMTI2Ii8+PHdvcmtib29rUHIgZGVmYXVsdFRoZW1lVmVyc2lvbj0iMTY2OTI1Ii8+PG1jOkFsdGVybmF0ZUNvbnRlbnQgeG1sbnM6bWM9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9tYXJrdXAtY29tcGF0aWJpbGl0eS8yMDA2Ij48bWM6Q2hvaWNlIFJlcXVpcmVzPSJ4MTUiPjx4MTVhYzphYnNQYXRoIHVybD0iSDpcVFJFQlx0cmViLWV4cG9ydFx0ZW1wbGF0ZVwiIHhtbG5zOngxNWFjPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTAvMTEvYWMiLz48L21jOkNob2ljZT48L21jOkFsdGVybmF0ZUNvbnRlbnQ+PHhyOnJldmlzaW9uUHRyIHJldklETGFzdFNhdmU9IjAiIGRvY3VtZW50SWQ9Ijhfe0Q4NThGOUY3LTBEOTItNEFFNC04QTQyLTQ4MENCMzU5QjYyRH0iIHhyNjpjb2F1dGhWZXJzaW9uTGFzdD0iNDAiIHhyNjpjb2F1dGhWZXJzaW9uTWF4PSI0MCIgeHIxMDp1aWRMYXN0U2F2ZT0iezAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMH0iLz48Ym9va1ZpZXdzPjx3b3JrYm9va1ZpZXcgeFdpbmRvdz0iMCIgeVdpbmRvdz0iMCIgd2luZG93V2lkdGg9IjI0NTcwIiB3aW5kb3dIZWlnaHQ9IjExMTMwIiB4cjI6dWlkPSJ7REU0RTdEMzUtNDkyRC00MEQ3LTk5MjUtNDY0N0Y1ODdFMURFfSIvPjwvYm9va1ZpZXdzPjxzaGVldHM+PHNoZWV0IG5hbWU9IlNoZWV0MSIgc2hlZXRJZD0iMSIgcjppZD0icklkMSIvPjwvc2hlZXRzPjxjYWxjUHIgY2FsY0lkPSIxOTEwMjkiLz48ZXh0THN0PjxleHQgdXJpPSJ7MTQwQTcwOTQtMEUzNS00ODkyLTg0MzItQzREMkU1N0VERUI1fSIgeG1sbnM6eDE1PSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTAvMTEvbWFpbiI+PHgxNTp3b3JrYm9va1ByIGNoYXJ0VHJhY2tpbmdSZWZCYXNlPSIxIi8+PC9leHQ+PC9leHRMc3Q+PC93b3JrYm9vaz5QSwMECgAAAAAAAAAhAIE+lJe6AgAAugIAABoAAAB4bC9fcmVscy93b3JrYm9vay54bWwucmVsczw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz4NCjxSZWxhdGlvbnNoaXBzIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvcGFja2FnZS8yMDA2L3JlbGF0aW9uc2hpcHMiPjxSZWxhdGlvbnNoaXAgSWQ9InJJZDMiIFR5cGU9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L3JlbGF0aW9uc2hpcHMvc3R5bGVzIiBUYXJnZXQ9InN0eWxlcy54bWwiLz48UmVsYXRpb25zaGlwIElkPSJySWQyIiBUeXBlPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzL3RoZW1lIiBUYXJnZXQ9InRoZW1lL3RoZW1lMS54bWwiLz48UmVsYXRpb25zaGlwIElkPSJySWQxIiBUeXBlPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzL3dvcmtzaGVldCIgVGFyZ2V0PSJ3b3Jrc2hlZXRzL3NoZWV0MS54bWwiLz48UmVsYXRpb25zaGlwIElkPSJySWQ0IiBUeXBlPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzL3NoYXJlZFN0cmluZ3MiIFRhcmdldD0ic2hhcmVkU3RyaW5ncy54bWwiLz48L1JlbGF0aW9uc2hpcHM+UEsDBAoAAAAAAAAAIQACrURzpAMAAKQDAAAYAAAAeGwvd29ya3NoZWV0cy9zaGVldDEueG1sPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPHdvcmtzaGVldCB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3NwcmVhZHNoZWV0bWwvMjAwNi9tYWluIiB4bWxuczpyPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvb2ZmaWNlRG9jdW1lbnQvMjAwNi9yZWxhdGlvbnNoaXBzIiB4bWxuczptYz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL21hcmt1cC1jb21wYXRpYmlsaXR5LzIwMDYiIG1jOklnbm9yYWJsZT0ieDE0YWMgeHIgeHIyIHhyMyIgeG1sbnM6eDE0YWM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAwOS85L2FjIiB4bWxuczp4cj0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2Uvc3ByZWFkc2hlZXRtbC8yMDE0L3JldmlzaW9uIiB4bWxuczp4cjI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAxNS9yZXZpc2lvbjIiIHhtbG5zOnhyMz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2Uvc3ByZWFkc2hlZXRtbC8yMDE2L3JldmlzaW9uMyIgeHI6dWlkPSJ7MEQ4RTVDQTItNUM5RS00RDRCLTk0QzUtRjM1QzA0MUYzOUJEfSI+PGRpbWVuc2lvbiByZWY9IkExIi8+PHNoZWV0Vmlld3M+PHNoZWV0VmlldyB0YWJTZWxlY3RlZD0iMSIgd29ya2Jvb2tWaWV3SWQ9IjAiLz48L3NoZWV0Vmlld3M+PHNoZWV0Rm9ybWF0UHIgZGVmYXVsdFJvd0hlaWdodD0iMTUiIHgxNGFjOmR5RGVzY2VudD0iMC4yNSIvPjxzaGVldERhdGEvPjxwYWdlTWFyZ2lucyBsZWZ0PSIwLjciIHJpZ2h0PSIwLjciIHRvcD0iMC43NSIgYm90dG9tPSIwLjc1IiBoZWFkZXI9IjAuMyIgZm9vdGVyPSIwLjMiLz48L3dvcmtzaGVldD5QSwMECgAAAAAAAAAhAMEXEL7GIAAAxiAAABMAAAB4bC90aGVtZS90aGVtZTEueG1sPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPGE6dGhlbWUgeG1sbnM6YT0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL2RyYXdpbmdtbC8yMDA2L21haW4iIG5hbWU9Ik9mZmljZSBUaGVtZSI+PGE6dGhlbWVFbGVtZW50cz48YTpjbHJTY2hlbWUgbmFtZT0iT2ZmaWNlIj48YTpkazE+PGE6c3lzQ2xyIHZhbD0id2luZG93VGV4dCIgbGFzdENscj0iMDAwMDAwIi8+PC9hOmRrMT48YTpsdDE+PGE6c3lzQ2xyIHZhbD0id2luZG93IiBsYXN0Q2xyPSJGRkZGRkYiLz48L2E6bHQxPjxhOmRrMj48YTpzcmdiQ2xyIHZhbD0iNDQ1NDZBIi8+PC9hOmRrMj48YTpsdDI+PGE6c3JnYkNsciB2YWw9IkU3RTZFNiIvPjwvYTpsdDI+PGE6YWNjZW50MT48YTpzcmdiQ2xyIHZhbD0iNDQ3MkM0Ii8+PC9hOmFjY2VudDE+PGE6YWNjZW50Mj48YTpzcmdiQ2xyIHZhbD0iRUQ3RDMxIi8+PC9hOmFjY2VudDI+PGE6YWNjZW50Mz48YTpzcmdiQ2xyIHZhbD0iQTVBNUE1Ii8+PC9hOmFjY2VudDM+PGE6YWNjZW50ND48YTpzcmdiQ2xyIHZhbD0iRkZDMDAwIi8+PC9hOmFjY2VudDQ+PGE6YWNjZW50NT48YTpzcmdiQ2xyIHZhbD0iNUI5QkQ1Ii8+PC9hOmFjY2VudDU+PGE6YWNjZW50Nj48YTpzcmdiQ2xyIHZhbD0iNzBBRDQ3Ii8+PC9hOmFjY2VudDY+PGE6aGxpbms+PGE6c3JnYkNsciB2YWw9IjA1NjNDMSIvPjwvYTpobGluaz48YTpmb2xIbGluaz48YTpzcmdiQ2xyIHZhbD0iOTU0RjcyIi8+PC9hOmZvbEhsaW5rPjwvYTpjbHJTY2hlbWU+PGE6Zm9udFNjaGVtZSBuYW1lPSJPZmZpY2UiPjxhOm1ham9yRm9udD48YTpsYXRpbiB0eXBlZmFjZT0iQ2FsaWJyaSBMaWdodCIgcGFub3NlPSIwMjBGMDMwMjAyMDIwNDAzMDIwNCIvPjxhOmVhIHR5cGVmYWNlPSIiLz48YTpjcyB0eXBlZmFjZT0iIi8+PGE6Zm9udCBzY3JpcHQ9IkpwYW4iIHR5cGVmYWNlPSLmuLjjgrTjgrfjg4Pjgq8gTGlnaHQiLz48YTpmb250IHNjcmlwdD0iSGFuZyIgdHlwZWZhY2U9IuunkeydgCDqs6DrlJUiLz48YTpmb250IHNjcmlwdD0iSGFucyIgdHlwZWZhY2U9Iuetiee6vyBMaWdodCIvPjxhOmZvbnQgc2NyaXB0PSJIYW50IiB0eXBlZmFjZT0i5paw57Sw5piO6auUIi8+PGE6Zm9udCBzY3JpcHQ9IkFyYWIiIHR5cGVmYWNlPSJUaW1lcyBOZXcgUm9tYW4iLz48YTpmb250IHNjcmlwdD0iSGViciIgdHlwZWZhY2U9IlRpbWVzIE5ldyBSb21hbiIvPjxhOmZvbnQgc2NyaXB0PSJUaGFpIiB0eXBlZmFjZT0iVGFob21hIi8+PGE6Zm9udCBzY3JpcHQ9IkV0aGkiIHR5cGVmYWNlPSJOeWFsYSIvPjxhOmZvbnQgc2NyaXB0PSJCZW5nIiB0eXBlZmFjZT0iVnJpbmRhIi8+PGE6Zm9udCBzY3JpcHQ9Ikd1anIiIHR5cGVmYWNlPSJTaHJ1dGkiLz48YTpmb250IHNjcmlwdD0iS2htciIgdHlwZWZhY2U9Ik1vb2xCb3JhbiIvPjxhOmZvbnQgc2NyaXB0PSJLbmRhIiB0eXBlZmFjZT0iVHVuZ2EiLz48YTpmb250IHNjcmlwdD0iR3VydSIgdHlwZWZhY2U9IlJhYXZpIi8+PGE6Zm9udCBzY3JpcHQ9IkNhbnMiIHR5cGVmYWNlPSJFdXBoZW1pYSIvPjxhOmZvbnQgc2NyaXB0PSJDaGVyIiB0eXBlZmFjZT0iUGxhbnRhZ2VuZXQgQ2hlcm9rZWUiLz48YTpmb250IHNjcmlwdD0iWWlpaSIgdHlwZWZhY2U9Ik1pY3Jvc29mdCBZaSBCYWl0aSIvPjxhOmZvbnQgc2NyaXB0PSJUaWJ0IiB0eXBlZmFjZT0iTWljcm9zb2Z0IEhpbWFsYXlhIi8+PGE6Zm9udCBzY3JpcHQ9IlRoYWEiIHR5cGVmYWNlPSJNViBCb2xpIi8+PGE6Zm9udCBzY3JpcHQ9IkRldmEiIHR5cGVmYWNlPSJNYW5nYWwiLz48YTpmb250IHNjcmlwdD0iVGVsdSIgdHlwZWZhY2U9IkdhdXRhbWkiLz48YTpmb250IHNjcmlwdD0iVGFtbCIgdHlwZWZhY2U9IkxhdGhhIi8+PGE6Zm9udCBzY3JpcHQ9IlN5cmMiIHR5cGVmYWNlPSJFc3RyYW5nZWxvIEVkZXNzYSIvPjxhOmZvbnQgc2NyaXB0PSJPcnlhIiB0eXBlZmFjZT0iS2FsaW5nYSIvPjxhOmZvbnQgc2NyaXB0PSJNbHltIiB0eXBlZmFjZT0iS2FydGlrYSIvPjxhOmZvbnQgc2NyaXB0PSJMYW9vIiB0eXBlZmFjZT0iRG9rQ2hhbXBhIi8+PGE6Zm9udCBzY3JpcHQ9IlNpbmgiIHR5cGVmYWNlPSJJc2tvb2xhIFBvdGEiLz48YTpmb250IHNjcmlwdD0iTW9uZyIgdHlwZWZhY2U9Ik1vbmdvbGlhbiBCYWl0aSIvPjxhOmZvbnQgc2NyaXB0PSJWaWV0IiB0eXBlZmFjZT0iVGltZXMgTmV3IFJvbWFuIi8+PGE6Zm9udCBzY3JpcHQ9IlVpZ2giIHR5cGVmYWNlPSJNaWNyb3NvZnQgVWlnaHVyIi8+PGE6Zm9udCBzY3JpcHQ9Ikdlb3IiIHR5cGVmYWNlPSJTeWxmYWVuIi8+PGE6Zm9udCBzY3JpcHQ9IkFybW4iIHR5cGVmYWNlPSJBcmlhbCIvPjxhOmZvbnQgc2NyaXB0PSJCdWdpIiB0eXBlZmFjZT0iTGVlbGF3YWRlZSBVSSIvPjxhOmZvbnQgc2NyaXB0PSJCb3BvIiB0eXBlZmFjZT0iTWljcm9zb2Z0IEpoZW5nSGVpIi8+PGE6Zm9udCBzY3JpcHQ9IkphdmEiIHR5cGVmYWNlPSJKYXZhbmVzZSBUZXh0Ii8+PGE6Zm9udCBzY3JpcHQ9Ikxpc3UiIHR5cGVmYWNlPSJTZWdvZSBVSSIvPjxhOmZvbnQgc2NyaXB0PSJNeW1yIiB0eXBlZmFjZT0iTXlhbm1hciBUZXh0Ii8+PGE6Zm9udCBzY3JpcHQ9Ik5rb28iIHR5cGVmYWNlPSJFYnJpbWEiLz48YTpmb250IHNjcmlwdD0iT2xjayIgdHlwZWZhY2U9Ik5pcm1hbGEgVUkiLz48YTpmb250IHNjcmlwdD0iT3NtYSIgdHlwZWZhY2U9IkVicmltYSIvPjxhOmZvbnQgc2NyaXB0PSJQaGFnIiB0eXBlZmFjZT0iUGhhZ3NwYSIvPjxhOmZvbnQgc2NyaXB0PSJTeXJuIiB0eXBlZmFjZT0iRXN0cmFuZ2VsbyBFZGVzc2EiLz48YTpmb250IHNjcmlwdD0iU3lyaiIgdHlwZWZhY2U9IkVzdHJhbmdlbG8gRWRlc3NhIi8+PGE6Zm9udCBzY3JpcHQ9IlN5cmUiIHR5cGVmYWNlPSJFc3RyYW5nZWxvIEVkZXNzYSIvPjxhOmZvbnQgc2NyaXB0PSJTb3JhIiB0eXBlZmFjZT0iTmlybWFsYSBVSSIvPjxhOmZvbnQgc2NyaXB0PSJUYWxlIiB0eXBlZmFjZT0iTWljcm9zb2Z0IFRhaSBMZSIvPjxhOmZvbnQgc2NyaXB0PSJUYWx1IiB0eXBlZmFjZT0iTWljcm9zb2Z0IE5ldyBUYWkgTHVlIi8+PGE6Zm9udCBzY3JpcHQ9IlRmbmciIHR5cGVmYWNlPSJFYnJpbWEiLz48L2E6bWFqb3JGb250PjxhOm1pbm9yRm9udD48YTpsYXRpbiB0eXBlZmFjZT0iQ2FsaWJyaSIgcGFub3NlPSIwMjBGMDUwMjAyMDIwNDAzMDIwNCIvPjxhOmVhIHR5cGVmYWNlPSIiLz48YTpjcyB0eXBlZmFjZT0iIi8+PGE6Zm9udCBzY3JpcHQ9IkpwYW4iIHR5cGVmYWNlPSLmuLjjgrTjgrfjg4Pjgq8iLz48YTpmb250IHNjcmlwdD0iSGFuZyIgdHlwZWZhY2U9IuunkeydgCDqs6DrlJUiLz48YTpmb250IHNjcmlwdD0iSGFucyIgdHlwZWZhY2U9Iuetiee6vyIvPjxhOmZvbnQgc2NyaXB0PSJIYW50IiB0eXBlZmFjZT0i5paw57Sw5piO6auUIi8+PGE6Zm9udCBzY3JpcHQ9IkFyYWIiIHR5cGVmYWNlPSJBcmlhbCIvPjxhOmZvbnQgc2NyaXB0PSJIZWJyIiB0eXBlZmFjZT0iQXJpYWwiLz48YTpmb250IHNjcmlwdD0iVGhhaSIgdHlwZWZhY2U9IlRhaG9tYSIvPjxhOmZvbnQgc2NyaXB0PSJFdGhpIiB0eXBlZmFjZT0iTnlhbGEiLz48YTpmb250IHNjcmlwdD0iQmVuZyIgdHlwZWZhY2U9IlZyaW5kYSIvPjxhOmZvbnQgc2NyaXB0PSJHdWpyIiB0eXBlZmFjZT0iU2hydXRpIi8+PGE6Zm9udCBzY3JpcHQ9IktobXIiIHR5cGVmYWNlPSJEYXVuUGVuaCIvPjxhOmZvbnQgc2NyaXB0PSJLbmRhIiB0eXBlZmFjZT0iVHVuZ2EiLz48YTpmb250IHNjcmlwdD0iR3VydSIgdHlwZWZhY2U9IlJhYXZpIi8+PGE6Zm9udCBzY3JpcHQ9IkNhbnMiIHR5cGVmYWNlPSJFdXBoZW1pYSIvPjxhOmZvbnQgc2NyaXB0PSJDaGVyIiB0eXBlZmFjZT0iUGxhbnRhZ2VuZXQgQ2hlcm9rZWUiLz48YTpmb250IHNjcmlwdD0iWWlpaSIgdHlwZWZhY2U9Ik1pY3Jvc29mdCBZaSBCYWl0aSIvPjxhOmZvbnQgc2NyaXB0PSJUaWJ0IiB0eXBlZmFjZT0iTWljcm9zb2Z0IEhpbWFsYXlhIi8+PGE6Zm9udCBzY3JpcHQ9IlRoYWEiIHR5cGVmYWNlPSJNViBCb2xpIi8+PGE6Zm9udCBzY3JpcHQ9IkRldmEiIHR5cGVmYWNlPSJNYW5nYWwiLz48YTpmb250IHNjcmlwdD0iVGVsdSIgdHlwZWZhY2U9IkdhdXRhbWkiLz48YTpmb250IHNjcmlwdD0iVGFtbCIgdHlwZWZhY2U9IkxhdGhhIi8+PGE6Zm9udCBzY3JpcHQ9IlN5cmMiIHR5cGVmYWNlPSJFc3RyYW5nZWxvIEVkZXNzYSIvPjxhOmZvbnQgc2NyaXB0PSJPcnlhIiB0eXBlZmFjZT0iS2FsaW5nYSIvPjxhOmZvbnQgc2NyaXB0PSJNbHltIiB0eXBlZmFjZT0iS2FydGlrYSIvPjxhOmZvbnQgc2NyaXB0PSJMYW9vIiB0eXBlZmFjZT0iRG9rQ2hhbXBhIi8+PGE6Zm9udCBzY3JpcHQ9IlNpbmgiIHR5cGVmYWNlPSJJc2tvb2xhIFBvdGEiLz48YTpmb250IHNjcmlwdD0iTW9uZyIgdHlwZWZhY2U9Ik1vbmdvbGlhbiBCYWl0aSIvPjxhOmZvbnQgc2NyaXB0PSJWaWV0IiB0eXBlZmFjZT0iQXJpYWwiLz48YTpmb250IHNjcmlwdD0iVWlnaCIgdHlwZWZhY2U9Ik1pY3Jvc29mdCBVaWdodXIiLz48YTpmb250IHNjcmlwdD0iR2VvciIgdHlwZWZhY2U9IlN5bGZhZW4iLz48YTpmb250IHNjcmlwdD0iQXJtbiIgdHlwZWZhY2U9IkFyaWFsIi8+PGE6Zm9udCBzY3JpcHQ9IkJ1Z2kiIHR5cGVmYWNlPSJMZWVsYXdhZGVlIFVJIi8+PGE6Zm9udCBzY3JpcHQ9IkJvcG8iIHR5cGVmYWNlPSJNaWNyb3NvZnQgSmhlbmdIZWkiLz48YTpmb250IHNjcmlwdD0iSmF2YSIgdHlwZWZhY2U9IkphdmFuZXNlIFRleHQiLz48YTpmb250IHNjcmlwdD0iTGlzdSIgdHlwZWZhY2U9IlNlZ29lIFVJIi8+PGE6Zm9udCBzY3JpcHQ9Ik15bXIiIHR5cGVmYWNlPSJNeWFubWFyIFRleHQiLz48YTpmb250IHNjcmlwdD0iTmtvbyIgdHlwZWZhY2U9IkVicmltYSIvPjxhOmZvbnQgc2NyaXB0PSJPbGNrIiB0eXBlZmFjZT0iTmlybWFsYSBVSSIvPjxhOmZvbnQgc2NyaXB0PSJPc21hIiB0eXBlZmFjZT0iRWJyaW1hIi8+PGE6Zm9udCBzY3JpcHQ9IlBoYWciIHR5cGVmYWNlPSJQaGFnc3BhIi8+PGE6Zm9udCBzY3JpcHQ9IlN5cm4iIHR5cGVmYWNlPSJFc3RyYW5nZWxvIEVkZXNzYSIvPjxhOmZvbnQgc2NyaXB0PSJTeXJqIiB0eXBlZmFjZT0iRXN0cmFuZ2VsbyBFZGVzc2EiLz48YTpmb250IHNjcmlwdD0iU3lyZSIgdHlwZWZhY2U9IkVzdHJhbmdlbG8gRWRlc3NhIi8+PGE6Zm9udCBzY3JpcHQ9IlNvcmEiIHR5cGVmYWNlPSJOaXJtYWxhIFVJIi8+PGE6Zm9udCBzY3JpcHQ9IlRhbGUiIHR5cGVmYWNlPSJNaWNyb3NvZnQgVGFpIExlIi8+PGE6Zm9udCBzY3JpcHQ9IlRhbHUiIHR5cGVmYWNlPSJNaWNyb3NvZnQgTmV3IFRhaSBMdWUiLz48YTpmb250IHNjcmlwdD0iVGZuZyIgdHlwZWZhY2U9IkVicmltYSIvPjwvYTptaW5vckZvbnQ+PC9hOmZvbnRTY2hlbWU+PGE6Zm10U2NoZW1lIG5hbWU9Ik9mZmljZSI+PGE6ZmlsbFN0eWxlTHN0PjxhOnNvbGlkRmlsbD48YTpzY2hlbWVDbHIgdmFsPSJwaENsciIvPjwvYTpzb2xpZEZpbGw+PGE6Z3JhZEZpbGwgcm90V2l0aFNoYXBlPSIxIj48YTpnc0xzdD48YTpncyBwb3M9IjAiPjxhOnNjaGVtZUNsciB2YWw9InBoQ2xyIj48YTpsdW1Nb2QgdmFsPSIxMTAwMDAiLz48YTpzYXRNb2QgdmFsPSIxMDUwMDAiLz48YTp0aW50IHZhbD0iNjcwMDAiLz48L2E6c2NoZW1lQ2xyPjwvYTpncz48YTpncyBwb3M9IjUwMDAwIj48YTpzY2hlbWVDbHIgdmFsPSJwaENsciI+PGE6bHVtTW9kIHZhbD0iMTA1MDAwIi8+PGE6c2F0TW9kIHZhbD0iMTAzMDAwIi8+PGE6dGludCB2YWw9IjczMDAwIi8+PC9hOnNjaGVtZUNscj48L2E6Z3M+PGE6Z3MgcG9zPSIxMDAwMDAiPjxhOnNjaGVtZUNsciB2YWw9InBoQ2xyIj48YTpsdW1Nb2QgdmFsPSIxMDUwMDAiLz48YTpzYXRNb2QgdmFsPSIxMDkwMDAiLz48YTp0aW50IHZhbD0iODEwMDAiLz48L2E6c2NoZW1lQ2xyPjwvYTpncz48L2E6Z3NMc3Q+PGE6bGluIGFuZz0iNTQwMDAwMCIgc2NhbGVkPSIwIi8+PC9hOmdyYWRGaWxsPjxhOmdyYWRGaWxsIHJvdFdpdGhTaGFwZT0iMSI+PGE6Z3NMc3Q+PGE6Z3MgcG9zPSIwIj48YTpzY2hlbWVDbHIgdmFsPSJwaENsciI+PGE6c2F0TW9kIHZhbD0iMTAzMDAwIi8+PGE6bHVtTW9kIHZhbD0iMTAyMDAwIi8+PGE6dGludCB2YWw9Ijk0MDAwIi8+PC9hOnNjaGVtZUNscj48L2E6Z3M+PGE6Z3MgcG9zPSI1MDAwMCI+PGE6c2NoZW1lQ2xyIHZhbD0icGhDbHIiPjxhOnNhdE1vZCB2YWw9IjExMDAwMCIvPjxhOmx1bU1vZCB2YWw9IjEwMDAwMCIvPjxhOnNoYWRlIHZhbD0iMTAwMDAwIi8+PC9hOnNjaGVtZUNscj48L2E6Z3M+PGE6Z3MgcG9zPSIxMDAwMDAiPjxhOnNjaGVtZUNsciB2YWw9InBoQ2xyIj48YTpsdW1Nb2QgdmFsPSI5OTAwMCIvPjxhOnNhdE1vZCB2YWw9IjEyMDAwMCIvPjxhOnNoYWRlIHZhbD0iNzgwMDAiLz48L2E6c2NoZW1lQ2xyPjwvYTpncz48L2E6Z3NMc3Q+PGE6bGluIGFuZz0iNTQwMDAwMCIgc2NhbGVkPSIwIi8+PC9hOmdyYWRGaWxsPjwvYTpmaWxsU3R5bGVMc3Q+PGE6bG5TdHlsZUxzdD48YTpsbiB3PSI2MzUwIiBjYXA9ImZsYXQiIGNtcGQ9InNuZyIgYWxnbj0iY3RyIj48YTpzb2xpZEZpbGw+PGE6c2NoZW1lQ2xyIHZhbD0icGhDbHIiLz48L2E6c29saWRGaWxsPjxhOnByc3REYXNoIHZhbD0ic29saWQiLz48YTptaXRlciBsaW09IjgwMDAwMCIvPjwvYTpsbj48YTpsbiB3PSIxMjcwMCIgY2FwPSJmbGF0IiBjbXBkPSJzbmciIGFsZ249ImN0ciI+PGE6c29saWRGaWxsPjxhOnNjaGVtZUNsciB2YWw9InBoQ2xyIi8+PC9hOnNvbGlkRmlsbD48YTpwcnN0RGFzaCB2YWw9InNvbGlkIi8+PGE6bWl0ZXIgbGltPSI4MDAwMDAiLz48L2E6bG4+PGE6bG4gdz0iMTkwNTAiIGNhcD0iZmxhdCIgY21wZD0ic25nIiBhbGduPSJjdHIiPjxhOnNvbGlkRmlsbD48YTpzY2hlbWVDbHIgdmFsPSJwaENsciIvPjwvYTpzb2xpZEZpbGw+PGE6cHJzdERhc2ggdmFsPSJzb2xpZCIvPjxhOm1pdGVyIGxpbT0iODAwMDAwIi8+PC9hOmxuPjwvYTpsblN0eWxlTHN0PjxhOmVmZmVjdFN0eWxlTHN0PjxhOmVmZmVjdFN0eWxlPjxhOmVmZmVjdExzdC8+PC9hOmVmZmVjdFN0eWxlPjxhOmVmZmVjdFN0eWxlPjxhOmVmZmVjdExzdC8+PC9hOmVmZmVjdFN0eWxlPjxhOmVmZmVjdFN0eWxlPjxhOmVmZmVjdExzdD48YTpvdXRlclNoZHcgYmx1clJhZD0iNTcxNTAiIGRpc3Q9IjE5MDUwIiBkaXI9IjU0MDAwMDAiIGFsZ249ImN0ciIgcm90V2l0aFNoYXBlPSIwIj48YTpzcmdiQ2xyIHZhbD0iMDAwMDAwIj48YTphbHBoYSB2YWw9IjYzMDAwIi8+PC9hOnNyZ2JDbHI+PC9hOm91dGVyU2hkdz48L2E6ZWZmZWN0THN0PjwvYTplZmZlY3RTdHlsZT48L2E6ZWZmZWN0U3R5bGVMc3Q+PGE6YmdGaWxsU3R5bGVMc3Q+PGE6c29saWRGaWxsPjxhOnNjaGVtZUNsciB2YWw9InBoQ2xyIi8+PC9hOnNvbGlkRmlsbD48YTpzb2xpZEZpbGw+PGE6c2NoZW1lQ2xyIHZhbD0icGhDbHIiPjxhOnRpbnQgdmFsPSI5NTAwMCIvPjxhOnNhdE1vZCB2YWw9IjE3MDAwMCIvPjwvYTpzY2hlbWVDbHI+PC9hOnNvbGlkRmlsbD48YTpncmFkRmlsbCByb3RXaXRoU2hhcGU9IjEiPjxhOmdzTHN0PjxhOmdzIHBvcz0iMCI+PGE6c2NoZW1lQ2xyIHZhbD0icGhDbHIiPjxhOnRpbnQgdmFsPSI5MzAwMCIvPjxhOnNhdE1vZCB2YWw9IjE1MDAwMCIvPjxhOnNoYWRlIHZhbD0iOTgwMDAiLz48YTpsdW1Nb2QgdmFsPSIxMDIwMDAiLz48L2E6c2NoZW1lQ2xyPjwvYTpncz48YTpncyBwb3M9IjUwMDAwIj48YTpzY2hlbWVDbHIgdmFsPSJwaENsciI+PGE6dGludCB2YWw9Ijk4MDAwIi8+PGE6c2F0TW9kIHZhbD0iMTMwMDAwIi8+PGE6c2hhZGUgdmFsPSI5MDAwMCIvPjxhOmx1bU1vZCB2YWw9IjEwMzAwMCIvPjwvYTpzY2hlbWVDbHI+PC9hOmdzPjxhOmdzIHBvcz0iMTAwMDAwIj48YTpzY2hlbWVDbHIgdmFsPSJwaENsciI+PGE6c2hhZGUgdmFsPSI2MzAwMCIvPjxhOnNhdE1vZCB2YWw9IjEyMDAwMCIvPjwvYTpzY2hlbWVDbHI+PC9hOmdzPjwvYTpnc0xzdD48YTpsaW4gYW5nPSI1NDAwMDAwIiBzY2FsZWQ9IjAiLz48L2E6Z3JhZEZpbGw+PC9hOmJnRmlsbFN0eWxlTHN0PjwvYTpmbXRTY2hlbWU+PC9hOnRoZW1lRWxlbWVudHM+PGE6b2JqZWN0RGVmYXVsdHMvPjxhOmV4dHJhQ2xyU2NoZW1lTHN0Lz48YTpleHRMc3Q+PGE6ZXh0IHVyaT0iezA1QTRDMjVDLTA4NUUtNDM0MC04NUEzLUE1NTMxRTUxMERCMn0iPjx0aG0xNTp0aGVtZUZhbWlseSB4bWxuczp0aG0xNT0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2UvdGhlbWVtbC8yMDEyL21haW4iIG5hbWU9Ik9mZmljZSBUaGVtZSIgaWQ9Ins2MkY5MzlCNi05M0FGLTREQjgtOUM2Qi1ENkM3REZEQzU4OUZ9IiB2aWQ9Ins0QTNDNDZFOC02MUNDLTQ2MDMtQTU4OS03NDIyQTQ3QThFNEF9Ii8+PC9hOmV4dD48L2E6ZXh0THN0PjwvYTp0aGVtZT5QSwMECgAAAAAAAAAhAHmhgGxSBgAAUgYAAA0AAAB4bC9zdHlsZXMueG1sPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPHN0eWxlU2hlZXQgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9zcHJlYWRzaGVldG1sLzIwMDYvbWFpbiIgeG1sbnM6bWM9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9tYXJrdXAtY29tcGF0aWJpbGl0eS8yMDA2IiBtYzpJZ25vcmFibGU9IngxNGFjIHgxNnIyIHhyIiB4bWxuczp4MTRhYz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2Uvc3ByZWFkc2hlZXRtbC8yMDA5LzkvYWMiIHhtbG5zOngxNnIyPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTUvMDIvbWFpbiIgeG1sbnM6eHI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAxNC9yZXZpc2lvbiI+PGZvbnRzIGNvdW50PSIxIiB4MTRhYzprbm93bkZvbnRzPSIxIj48Zm9udD48c3ogdmFsPSIxMSIvPjxjb2xvciB0aGVtZT0iMSIvPjxuYW1lIHZhbD0iQ2FsaWJyaSIvPjxmYW1pbHkgdmFsPSIyIi8+PHNjaGVtZSB2YWw9Im1pbm9yIi8+PC9mb250PjwvZm9udHM+PGZpbGxzIGNvdW50PSIyIj48ZmlsbD48cGF0dGVybkZpbGwgcGF0dGVyblR5cGU9Im5vbmUiLz48L2ZpbGw+PGZpbGw+PHBhdHRlcm5GaWxsIHBhdHRlcm5UeXBlPSJncmF5MTI1Ii8+PC9maWxsPjwvZmlsbHM+PGJvcmRlcnMgY291bnQ9IjEiPjxib3JkZXI+PGxlZnQvPjxyaWdodC8+PHRvcC8+PGJvdHRvbS8+PGRpYWdvbmFsLz48L2JvcmRlcj48L2JvcmRlcnM+PGNlbGxTdHlsZVhmcyBjb3VudD0iMSI+PHhmIG51bUZtdElkPSIwIiBmb250SWQ9IjAiIGZpbGxJZD0iMCIgYm9yZGVySWQ9IjAiLz48L2NlbGxTdHlsZVhmcz48Y2VsbFhmcyBjb3VudD0iMSI+PHhmIG51bUZtdElkPSIwIiBmb250SWQ9IjAiIGZpbGxJZD0iMCIgYm9yZGVySWQ9IjAiIHhmSWQ9IjAiLz48L2NlbGxYZnM+PGNlbGxTdHlsZXMgY291bnQ9IjEiPjxjZWxsU3R5bGUgbmFtZT0iTm9ybWFsIiB4ZklkPSIwIiBidWlsdGluSWQ9IjAiLz48L2NlbGxTdHlsZXM+PGR4ZnMgY291bnQ9IjAiLz48dGFibGVTdHlsZXMgY291bnQ9IjAiIGRlZmF1bHRUYWJsZVN0eWxlPSJUYWJsZVN0eWxlTWVkaXVtMiIgZGVmYXVsdFBpdm90U3R5bGU9IlBpdm90U3R5bGVMaWdodDE2Ii8+PGV4dExzdD48ZXh0IHVyaT0ie0VCNzlERUYyLTgwQjgtNDNlNS05NUJELTU0Q0JEREY5MDIwQ30iIHhtbG5zOngxND0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2Uvc3ByZWFkc2hlZXRtbC8yMDA5LzkvbWFpbiI+PHgxNDpzbGljZXJTdHlsZXMgZGVmYXVsdFNsaWNlclN0eWxlPSJTbGljZXJTdHlsZUxpZ2h0MSIvPjwvZXh0PjxleHQgdXJpPSJ7OTI2MEE1MTAtRjMwMS00NmE4LTg2MzUtRjUxMkQ2NEJFNUY1fSIgeG1sbnM6eDE1PSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL29mZmljZS9zcHJlYWRzaGVldG1sLzIwMTAvMTEvbWFpbiI+PHgxNTp0aW1lbGluZVN0eWxlcyBkZWZhdWx0VGltZWxpbmVTdHlsZT0iVGltZVNsaWNlclN0eWxlTGlnaHQxIi8+PC9leHQ+PC9leHRMc3Q+PC9zdHlsZVNoZWV0PlBLAwQKAAAAAAAAACEA0IywC4EAAACBAAAAFAAAAHhsL3NoYXJlZFN0cmluZ3MueG1sPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPHNzdCB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL3NwcmVhZHNoZWV0bWwvMjAwNi9tYWluIi8+UEsDBAoAAAAAAAAAIQDcCx83XQIAAF0CAAARAAAAZG9jUHJvcHMvY29yZS54bWw8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCIgc3RhbmRhbG9uZT0ieWVzIj8+DQo8Y3A6Y29yZVByb3BlcnRpZXMgeG1sbnM6Y3A9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9wYWNrYWdlLzIwMDYvbWV0YWRhdGEvY29yZS1wcm9wZXJ0aWVzIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOmRjdGVybXM9Imh0dHA6Ly9wdXJsLm9yZy9kYy90ZXJtcy8iIHhtbG5zOmRjbWl0eXBlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIj48ZGM6Y3JlYXRvcj5kdW5jYW48L2RjOmNyZWF0b3I+PGNwOmxhc3RNb2RpZmllZEJ5PmR1bmNhbjwvY3A6bGFzdE1vZGlmaWVkQnk+PGRjdGVybXM6Y3JlYXRlZCB4c2k6dHlwZT0iZGN0ZXJtczpXM0NEVEYiPjIwMTktMDEtMzFUMTY6NDg6MDNaPC9kY3Rlcm1zOmNyZWF0ZWQ+PGRjdGVybXM6bW9kaWZpZWQgeHNpOnR5cGU9ImRjdGVybXM6VzNDRFRGIj4yMDE5LTAxLTMxVDE2OjQ4OjI4WjwvZGN0ZXJtczptb2RpZmllZD48L2NwOmNvcmVQcm9wZXJ0aWVzPlBLAwQKAAAAAAAAACEAYUkJEBEDAAARAwAAEAAAAGRvY1Byb3BzL2FwcC54bWw8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJVVEYtOCIgc3RhbmRhbG9uZT0ieWVzIj8+DQo8UHJvcGVydGllcyB4bWxucz0iaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL29mZmljZURvY3VtZW50LzIwMDYvZXh0ZW5kZWQtcHJvcGVydGllcyIgeG1sbnM6dnQ9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L2RvY1Byb3BzVlR5cGVzIj48QXBwbGljYXRpb24+TWljcm9zb2Z0IEV4Y2VsPC9BcHBsaWNhdGlvbj48RG9jU2VjdXJpdHk+MDwvRG9jU2VjdXJpdHk+PFNjYWxlQ3JvcD5mYWxzZTwvU2NhbGVDcm9wPjxIZWFkaW5nUGFpcnM+PHZ0OnZlY3RvciBzaXplPSIyIiBiYXNlVHlwZT0idmFyaWFudCI+PHZ0OnZhcmlhbnQ+PHZ0Omxwc3RyPldvcmtzaGVldHM8L3Z0Omxwc3RyPjwvdnQ6dmFyaWFudD48dnQ6dmFyaWFudD48dnQ6aTQ+MTwvdnQ6aTQ+PC92dDp2YXJpYW50PjwvdnQ6dmVjdG9yPjwvSGVhZGluZ1BhaXJzPjxUaXRsZXNPZlBhcnRzPjx2dDp2ZWN0b3Igc2l6ZT0iMSIgYmFzZVR5cGU9Imxwc3RyIj48dnQ6bHBzdHI+U2hlZXQxPC92dDpscHN0cj48L3Z0OnZlY3Rvcj48L1RpdGxlc09mUGFydHM+PENvbXBhbnk+PC9Db21wYW55PjxMaW5rc1VwVG9EYXRlPmZhbHNlPC9MaW5rc1VwVG9EYXRlPjxTaGFyZWREb2M+ZmFsc2U8L1NoYXJlZERvYz48SHlwZXJsaW5rc0NoYW5nZWQ+ZmFsc2U8L0h5cGVybGlua3NDaGFuZ2VkPjxBcHBWZXJzaW9uPjE2LjAzMDA8L0FwcFZlcnNpb24+PC9Qcm9wZXJ0aWVzPlBLAQIUAAoAAAAAAAAAIQBi7p1okAQAAJAEAAATAAAAAAAAAAAAAAAAAAAAAABbQ29udGVudF9UeXBlc10ueG1sUEsBAhQACgAAAAAAAAAhALVVMCNMAgAATAIAAAsAAAAAAAAAAAAAAAAAwQQAAF9yZWxzLy5yZWxzUEsBAhQACgAAAAAAAAAhALpwnmbKBgAAygYAAA8AAAAAAAAAAAAAAAAANgcAAHhsL3dvcmtib29rLnhtbFBLAQIUAAoAAAAAAAAAIQCBPpSXugIAALoCAAAaAAAAAAAAAAAAAAAAAC0OAAB4bC9fcmVscy93b3JrYm9vay54bWwucmVsc1BLAQIUAAoAAAAAAAAAIQACrURzpAMAAKQDAAAYAAAAAAAAAAAAAAAAAB8RAAB4bC93b3Jrc2hlZXRzL3NoZWV0MS54bWxQSwECFAAKAAAAAAAAACEAwRcQvsYgAADGIAAAEwAAAAAAAAAAAAAAAAD5FAAAeGwvdGhlbWUvdGhlbWUxLnhtbFBLAQIUAAoAAAAAAAAAIQB5oYBsUgYAAFIGAAANAAAAAAAAAAAAAAAAAPA1AAB4bC9zdHlsZXMueG1sUEsBAhQACgAAAAAAAAAhANCMsAuBAAAAgQAAABQAAAAAAAAAAAAAAAAAbTwAAHhsL3NoYXJlZFN0cmluZ3MueG1sUEsBAhQACgAAAAAAAAAhANwLHzddAgAAXQIAABEAAAAAAAAAAAAAAAAAID0AAGRvY1Byb3BzL2NvcmUueG1sUEsBAhQACgAAAAAAAAAhAGFJCRARAwAAEQMAABAAAAAAAAAAAAAAAAAArD8AAGRvY1Byb3BzL2FwcC54bWxQSwUGAAAAAAoACgCAAgAA60IAAAAA';
@@ -0,0 +1,47 @@
1
+
2
+ /*==============================================================================
3
+ *
4
+ * unescape entities from xml. we were using `he` for this, which is great,
5
+ * but we need it for like 5 entities. we need a hammer where `he` is a nuke.
6
+ *
7
+ * still I'm not sure we're fully covered. we might need to do numbers, in
8
+ * various formats.
9
+ *
10
+ * also using regexps is guaranteed to break, eventually, when parsing markup.
11
+ * a proper parser would be better. but realistically, the kind of xml we are
12
+ * going to see is not going to have cdata or comments or escaped entities.
13
+ *
14
+ * famous last words.
15
+ *
16
+ *=============================================================================*/
17
+
18
+ const entities: Record<string, string> = {
19
+ '&lt;': '<',
20
+ '&gt;': '>',
21
+ '&amp;': '&',
22
+ '&quot;': '"',
23
+ '&apos;': `'`,
24
+ }
25
+
26
+ const regex = /&\w+;/g;
27
+
28
+ /**
29
+ * short version
30
+ */
31
+ const ShortVersion = (text: string): string => text.replace(regex, pattern => entities[pattern] || pattern);
32
+
33
+ /**
34
+ * noisy version for dev
35
+ */
36
+ const LongVersion = (text: string): string => {
37
+ return text.replace(regex, pattern => {
38
+ if (entities[pattern]) {
39
+ return entities[pattern];
40
+ }
41
+ console.warn('unmapped entity', pattern);
42
+ return pattern;
43
+ });
44
+ };
45
+
46
+ export const Unescape = ShortVersion;
47
+
@@ -0,0 +1,182 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ /**
23
+ * switching to a different xml library, and trying to simplify how
24
+ * we deal with XLSX files.
25
+ *
26
+ * the original impetus for the switch was CSP -- ElementTree uses eval
27
+ * (actually new Function(...)) which is blocked by CSP, and I don't want to
28
+ * allow it (or patch ET). so we swtiched to fast-xml-parser, but optimally we
29
+ * should not be reliant on the actual parser, if we can have some sort of
30
+ * common data structure.
31
+ *
32
+ * in any event, in the old scheme we were constantly updating the XML tree
33
+ * so we could write back. in the new scheme, we'll start from raw data, build
34
+ * a structure, and then generate XML from that.
35
+ *
36
+ * the primary problems we are going to run into are namespacing and output
37
+ * ordering, but we can probably get through it.
38
+ *
39
+ * output ordering may be the hardest one, because different browsers. if
40
+ * necessary we can custom roll the js -> xml side.
41
+ */
42
+
43
+
44
+ import { AddressType, RangeType, is_range } from './address-type';
45
+ import type { SharedStrings } from './shared-strings2';
46
+ import type { Drawing } from './drawing2/drawing2';
47
+ import type { RelationshipMap } from './relationship';
48
+
49
+ export interface SheetOptions {
50
+ name?: string;
51
+ id?: number;
52
+ rid?: any;
53
+ }
54
+
55
+ export interface RangeOptions {
56
+ merge?: boolean;
57
+ style?: number;
58
+ precalc?: boolean|string|number;
59
+ preserveStyle?: boolean;
60
+ type?: string;
61
+ array?: string;
62
+ }
63
+
64
+ export enum VisibleState {
65
+ visible,
66
+ hidden,
67
+ very_hidden,
68
+ }
69
+
70
+ export class Sheet {
71
+
72
+ public path?: string;
73
+ public rels_path?: string;
74
+ public rels: RelationshipMap = {};
75
+
76
+ public sheet_data: any = {};
77
+
78
+ public shared_strings?: SharedStrings;
79
+ public extent?: RangeType;
80
+
81
+ public visible_state?: VisibleState;
82
+
83
+ public tab_selected = false;
84
+ public default_width = 0;
85
+
86
+ public drawings: Drawing[] = [];
87
+
88
+ constructor(public options: SheetOptions = {}) {
89
+ }
90
+
91
+ /**
92
+ * A1 -> {row: 1, col: 1} etc.
93
+ * in the event of a range, { from: {}, to: {} }
94
+ */
95
+ public TranslateAddress(s: string): AddressType | RangeType {
96
+ s = s.toUpperCase();
97
+ let m = s.match(/([A-Z]+\d+):([A-Z]+\d+)/);
98
+ if (m) {
99
+ return {
100
+ from: this.TranslateAddress(m[1]) as AddressType,
101
+ to: this.TranslateAddress(m[2]) as AddressType,
102
+ };
103
+ }
104
+
105
+ let row = 0;
106
+ let col = 0;
107
+
108
+ m = s.match(/^([A-Z]+)(\d+)$/);
109
+
110
+ if (m) {
111
+ row = Number(m[2]);
112
+ col = 0;
113
+ const len = m[1].length;
114
+ for (let i = 0; i < len; i++) {
115
+ const c = (m[1].charCodeAt(i) - 64);
116
+ col = col * 26 + c;
117
+ }
118
+ }
119
+ return { row, col };
120
+ }
121
+
122
+ /**
123
+ * { row: 1, col: 1 } -> A1.
124
+ * for ranges, {from: {}, to: {}} -> A1:B2
125
+ */
126
+ public Address(r: AddressType | RangeType, absolute = false): string {
127
+ if (is_range(r)) {
128
+ return this.Address(r.from, absolute) + ':' + this.Address(r.to, absolute);
129
+ }
130
+ let c = '';
131
+ let col = r.col;
132
+ while (col > 0) {
133
+ const x = ((col - 1) % 26) + 1;
134
+ c = String.fromCharCode(64 + x) + c;
135
+ col = (col - x) / 26;
136
+ }
137
+ const s = r.sheet ? `'${r.sheet}'!` : '';
138
+ if (absolute) {
139
+ return `${s}$${c}$${r.row}`;
140
+ }
141
+ return s + c + r.row;
142
+ }
143
+
144
+
145
+ /**
146
+ * convert an address (either style) to BOTH A1 and R1C1
147
+ */
148
+ public NormalizeAddress(rng: string | AddressType | RangeType): { a: string, rc: RangeType|AddressType } {
149
+ let a: string;
150
+ let rc: AddressType | RangeType;
151
+ if (typeof rng === 'string') {
152
+ a = rng.toUpperCase();
153
+ rc = this.TranslateAddress(a);
154
+ }
155
+ else {
156
+ rc = rng;
157
+ a = this.Address(rc);
158
+ }
159
+ return { a, rc };
160
+ }
161
+
162
+ public Parse(): void {
163
+
164
+ // we can read column/row sizes in here, or anything else we need to do
165
+ // atm just extent
166
+
167
+ const dim = this.sheet_data.worksheet?.dimension?.a$?.ref;
168
+
169
+ const extent = this.TranslateAddress(dim || '');
170
+ if (is_range(extent)) {
171
+ this.extent = JSON.parse(JSON.stringify(extent));
172
+ }
173
+ else {
174
+ this.extent = {
175
+ from: JSON.parse(JSON.stringify(extent)),
176
+ to: JSON.parse(JSON.stringify(extent)),
177
+ };
178
+ }
179
+
180
+ }
181
+
182
+ }