@angular/compiler 19.0.0-next.1 → 19.0.0-next.11

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 (186) hide show
  1. package/LICENSE +21 -0
  2. package/fesm2022/compiler.mjs +5465 -4675
  3. package/fesm2022/compiler.mjs.map +1 -1
  4. package/index.d.ts +115 -15
  5. package/package.json +2 -4
  6. package/esm2022/compiler.mjs +0 -13
  7. package/esm2022/index.mjs +0 -13
  8. package/esm2022/public_api.mjs +0 -15
  9. package/esm2022/src/assertions.mjs +0 -31
  10. package/esm2022/src/chars.mjs +0 -90
  11. package/esm2022/src/compiler.mjs +0 -88
  12. package/esm2022/src/compiler_facade_interface.mjs +0 -29
  13. package/esm2022/src/config.mjs +0 -20
  14. package/esm2022/src/constant_pool.mjs +0 -285
  15. package/esm2022/src/core.mjs +0 -96
  16. package/esm2022/src/expression_parser/ast.mjs +0 -755
  17. package/esm2022/src/expression_parser/lexer.mjs +0 -421
  18. package/esm2022/src/expression_parser/parser.mjs +0 -1222
  19. package/esm2022/src/i18n/digest.mjs +0 -322
  20. package/esm2022/src/i18n/extractor_merger.mjs +0 -409
  21. package/esm2022/src/i18n/i18n_ast.mjs +0 -212
  22. package/esm2022/src/i18n/i18n_html_parser.mjs +0 -54
  23. package/esm2022/src/i18n/i18n_parser.mjs +0 -247
  24. package/esm2022/src/i18n/index.mjs +0 -16
  25. package/esm2022/src/i18n/message_bundle.mjs +0 -93
  26. package/esm2022/src/i18n/parse_util.mjs +0 -17
  27. package/esm2022/src/i18n/serializers/placeholder.mjs +0 -139
  28. package/esm2022/src/i18n/serializers/serializer.mjs +0 -77
  29. package/esm2022/src/i18n/serializers/xliff.mjs +0 -300
  30. package/esm2022/src/i18n/serializers/xliff2.mjs +0 -349
  31. package/esm2022/src/i18n/serializers/xmb.mjs +0 -188
  32. package/esm2022/src/i18n/serializers/xml_helper.mjs +0 -94
  33. package/esm2022/src/i18n/serializers/xtb.mjs +0 -186
  34. package/esm2022/src/i18n/translation_bundle.mjs +0 -164
  35. package/esm2022/src/injectable_compiler_2.mjs +0 -138
  36. package/esm2022/src/jit_compiler_facade.mjs +0 -681
  37. package/esm2022/src/ml_parser/ast.mjs +0 -167
  38. package/esm2022/src/ml_parser/defaults.mjs +0 -24
  39. package/esm2022/src/ml_parser/entities.mjs +0 -2144
  40. package/esm2022/src/ml_parser/html_parser.mjs +0 -18
  41. package/esm2022/src/ml_parser/html_tags.mjs +0 -156
  42. package/esm2022/src/ml_parser/html_whitespaces.mjs +0 -107
  43. package/esm2022/src/ml_parser/icu_ast_expander.mjs +0 -125
  44. package/esm2022/src/ml_parser/lexer.mjs +0 -1210
  45. package/esm2022/src/ml_parser/parser.mjs +0 -539
  46. package/esm2022/src/ml_parser/tags.mjs +0 -47
  47. package/esm2022/src/ml_parser/tokens.mjs +0 -9
  48. package/esm2022/src/ml_parser/xml_parser.mjs +0 -19
  49. package/esm2022/src/ml_parser/xml_tags.mjs +0 -32
  50. package/esm2022/src/output/abstract_emitter.mjs +0 -524
  51. package/esm2022/src/output/abstract_js_emitter.mjs +0 -130
  52. package/esm2022/src/output/map_util.mjs +0 -19
  53. package/esm2022/src/output/output_ast.mjs +0 -1301
  54. package/esm2022/src/output/output_jit.mjs +0 -138
  55. package/esm2022/src/output/output_jit_trusted_types.mjs +0 -100
  56. package/esm2022/src/output/source_map.mjs +0 -150
  57. package/esm2022/src/parse_util.mjs +0 -198
  58. package/esm2022/src/render3/partial/api.mjs +0 -9
  59. package/esm2022/src/render3/partial/class_metadata.mjs +0 -52
  60. package/esm2022/src/render3/partial/component.mjs +0 -197
  61. package/esm2022/src/render3/partial/directive.mjs +0 -264
  62. package/esm2022/src/render3/partial/factory.mjs +0 -35
  63. package/esm2022/src/render3/partial/injectable.mjs +0 -67
  64. package/esm2022/src/render3/partial/injector.mjs +0 -41
  65. package/esm2022/src/render3/partial/ng_module.mjs +0 -63
  66. package/esm2022/src/render3/partial/pipe.mjs +0 -50
  67. package/esm2022/src/render3/partial/util.mjs +0 -79
  68. package/esm2022/src/render3/r3_ast.mjs +0 -493
  69. package/esm2022/src/render3/r3_class_debug_info_compiler.mjs +0 -35
  70. package/esm2022/src/render3/r3_class_metadata_compiler.mjs +0 -92
  71. package/esm2022/src/render3/r3_control_flow.mjs +0 -421
  72. package/esm2022/src/render3/r3_deferred_blocks.mjs +0 -170
  73. package/esm2022/src/render3/r3_deferred_triggers.mjs +0 -316
  74. package/esm2022/src/render3/r3_factory.mjs +0 -200
  75. package/esm2022/src/render3/r3_identifiers.mjs +0 -480
  76. package/esm2022/src/render3/r3_injector_compiler.mjs +0 -28
  77. package/esm2022/src/render3/r3_jit.mjs +0 -29
  78. package/esm2022/src/render3/r3_module_compiler.mjs +0 -211
  79. package/esm2022/src/render3/r3_pipe_compiler.mjs +0 -35
  80. package/esm2022/src/render3/r3_template_transform.mjs +0 -560
  81. package/esm2022/src/render3/util.mjs +0 -90
  82. package/esm2022/src/render3/view/api.mjs +0 -14
  83. package/esm2022/src/render3/view/compiler.mjs +0 -546
  84. package/esm2022/src/render3/view/i18n/get_msg_utils.mjs +0 -113
  85. package/esm2022/src/render3/view/i18n/icu_serializer.mjs +0 -43
  86. package/esm2022/src/render3/view/i18n/localize_utils.mjs +0 -118
  87. package/esm2022/src/render3/view/i18n/meta.mjs +0 -259
  88. package/esm2022/src/render3/view/i18n/util.mjs +0 -70
  89. package/esm2022/src/render3/view/query_generation.mjs +0 -182
  90. package/esm2022/src/render3/view/t2_api.mjs +0 -9
  91. package/esm2022/src/render3/view/t2_binder.mjs +0 -823
  92. package/esm2022/src/render3/view/template.mjs +0 -113
  93. package/esm2022/src/render3/view/util.mjs +0 -192
  94. package/esm2022/src/resource_loader.mjs +0 -17
  95. package/esm2022/src/schema/dom_element_schema_registry.mjs +0 -471
  96. package/esm2022/src/schema/dom_security_schema.mjs +0 -96
  97. package/esm2022/src/schema/element_schema_registry.mjs +0 -10
  98. package/esm2022/src/schema/trusted_types_sinks.mjs +0 -41
  99. package/esm2022/src/selector.mjs +0 -400
  100. package/esm2022/src/shadow_css.mjs +0 -1053
  101. package/esm2022/src/style_url_resolver.mjs +0 -17
  102. package/esm2022/src/template/pipeline/ir/index.mjs +0 -18
  103. package/esm2022/src/template/pipeline/ir/src/enums.mjs +0 -503
  104. package/esm2022/src/template/pipeline/ir/src/expression.mjs +0 -997
  105. package/esm2022/src/template/pipeline/ir/src/handle.mjs +0 -13
  106. package/esm2022/src/template/pipeline/ir/src/operations.mjs +0 -261
  107. package/esm2022/src/template/pipeline/ir/src/ops/create.mjs +0 -405
  108. package/esm2022/src/template/pipeline/ir/src/ops/host.mjs +0 -25
  109. package/esm2022/src/template/pipeline/ir/src/ops/shared.mjs +0 -43
  110. package/esm2022/src/template/pipeline/ir/src/ops/update.mjs +0 -277
  111. package/esm2022/src/template/pipeline/ir/src/traits.mjs +0 -64
  112. package/esm2022/src/template/pipeline/ir/src/variable.mjs +0 -13
  113. package/esm2022/src/template/pipeline/src/compilation.mjs +0 -194
  114. package/esm2022/src/template/pipeline/src/conversion.mjs +0 -64
  115. package/esm2022/src/template/pipeline/src/emit.mjs +0 -238
  116. package/esm2022/src/template/pipeline/src/ingest.mjs +0 -1058
  117. package/esm2022/src/template/pipeline/src/instruction.mjs +0 -564
  118. package/esm2022/src/template/pipeline/src/phases/any_cast.mjs +0 -32
  119. package/esm2022/src/template/pipeline/src/phases/apply_i18n_expressions.mjs +0 -63
  120. package/esm2022/src/template/pipeline/src/phases/assign_i18n_slot_dependencies.mjs +0 -63
  121. package/esm2022/src/template/pipeline/src/phases/attribute_extraction.mjs +0 -138
  122. package/esm2022/src/template/pipeline/src/phases/binding_specialization.mjs +0 -75
  123. package/esm2022/src/template/pipeline/src/phases/chaining.mjs +0 -112
  124. package/esm2022/src/template/pipeline/src/phases/collapse_singleton_interpolations.mjs +0 -32
  125. package/esm2022/src/template/pipeline/src/phases/conditionals.mjs +0 -58
  126. package/esm2022/src/template/pipeline/src/phases/const_collection.mjs +0 -214
  127. package/esm2022/src/template/pipeline/src/phases/convert_i18n_bindings.mjs +0 -52
  128. package/esm2022/src/template/pipeline/src/phases/create_i18n_contexts.mjs +0 -105
  129. package/esm2022/src/template/pipeline/src/phases/deduplicate_text_bindings.mjs +0 -40
  130. package/esm2022/src/template/pipeline/src/phases/defer_configs.mjs +0 -29
  131. package/esm2022/src/template/pipeline/src/phases/defer_resolve_targets.mjs +0 -113
  132. package/esm2022/src/template/pipeline/src/phases/empty_elements.mjs +0 -47
  133. package/esm2022/src/template/pipeline/src/phases/expand_safe_reads.mjs +0 -192
  134. package/esm2022/src/template/pipeline/src/phases/extract_i18n_messages.mjs +0 -218
  135. package/esm2022/src/template/pipeline/src/phases/generate_advance.mjs +0 -66
  136. package/esm2022/src/template/pipeline/src/phases/generate_local_let_references.mjs +0 -29
  137. package/esm2022/src/template/pipeline/src/phases/generate_projection_def.mjs +0 -46
  138. package/esm2022/src/template/pipeline/src/phases/generate_variables.mjs +0 -170
  139. package/esm2022/src/template/pipeline/src/phases/has_const_expression_collection.mjs +0 -28
  140. package/esm2022/src/template/pipeline/src/phases/host_style_property_parsing.mjs +0 -81
  141. package/esm2022/src/template/pipeline/src/phases/i18n_const_collection.mjs +0 -309
  142. package/esm2022/src/template/pipeline/src/phases/i18n_text_extraction.mjs +0 -97
  143. package/esm2022/src/template/pipeline/src/phases/local_refs.mjs +0 -43
  144. package/esm2022/src/template/pipeline/src/phases/namespace.mjs +0 -26
  145. package/esm2022/src/template/pipeline/src/phases/naming.mjs +0 -179
  146. package/esm2022/src/template/pipeline/src/phases/next_context_merging.mjs +0 -75
  147. package/esm2022/src/template/pipeline/src/phases/ng_container.mjs +0 -29
  148. package/esm2022/src/template/pipeline/src/phases/nonbindable.mjs +0 -47
  149. package/esm2022/src/template/pipeline/src/phases/nullish_coalescing.mjs +0 -33
  150. package/esm2022/src/template/pipeline/src/phases/ordering.mjs +0 -140
  151. package/esm2022/src/template/pipeline/src/phases/parse_extracted_styles.mjs +0 -137
  152. package/esm2022/src/template/pipeline/src/phases/phase_remove_content_selectors.mjs +0 -42
  153. package/esm2022/src/template/pipeline/src/phases/pipe_creation.mjs +0 -74
  154. package/esm2022/src/template/pipeline/src/phases/pipe_variadic.mjs +0 -30
  155. package/esm2022/src/template/pipeline/src/phases/propagate_i18n_blocks.mjs +0 -81
  156. package/esm2022/src/template/pipeline/src/phases/pure_function_extraction.mjs +0 -55
  157. package/esm2022/src/template/pipeline/src/phases/pure_literal_structures.mjs +0 -58
  158. package/esm2022/src/template/pipeline/src/phases/reify.mjs +0 -433
  159. package/esm2022/src/template/pipeline/src/phases/remove_empty_bindings.mjs +0 -31
  160. package/esm2022/src/template/pipeline/src/phases/remove_i18n_contexts.mjs +0 -27
  161. package/esm2022/src/template/pipeline/src/phases/remove_illegal_let_references.mjs +0 -36
  162. package/esm2022/src/template/pipeline/src/phases/remove_unused_i18n_attrs.mjs +0 -33
  163. package/esm2022/src/template/pipeline/src/phases/resolve_contexts.mjs +0 -60
  164. package/esm2022/src/template/pipeline/src/phases/resolve_defer_deps_fns.mjs +0 -31
  165. package/esm2022/src/template/pipeline/src/phases/resolve_dollar_event.mjs +0 -36
  166. package/esm2022/src/template/pipeline/src/phases/resolve_i18n_element_placeholders.mjs +0 -266
  167. package/esm2022/src/template/pipeline/src/phases/resolve_i18n_expression_placeholders.mjs +0 -70
  168. package/esm2022/src/template/pipeline/src/phases/resolve_names.mjs +0 -124
  169. package/esm2022/src/template/pipeline/src/phases/resolve_sanitizers.mjs +0 -123
  170. package/esm2022/src/template/pipeline/src/phases/save_restore_view.mjs +0 -64
  171. package/esm2022/src/template/pipeline/src/phases/slot_allocation.mjs +0 -62
  172. package/esm2022/src/template/pipeline/src/phases/store_let_optimization.mjs +0 -35
  173. package/esm2022/src/template/pipeline/src/phases/style_binding_specialization.mjs +0 -42
  174. package/esm2022/src/template/pipeline/src/phases/temporary_variables.mjs +0 -87
  175. package/esm2022/src/template/pipeline/src/phases/track_fn_generation.mjs +0 -52
  176. package/esm2022/src/template/pipeline/src/phases/track_fn_optimization.mjs +0 -88
  177. package/esm2022/src/template/pipeline/src/phases/track_variables.mjs +0 -36
  178. package/esm2022/src/template/pipeline/src/phases/transform_two_way_binding_set.mjs +0 -43
  179. package/esm2022/src/template/pipeline/src/phases/var_counting.mjs +0 -155
  180. package/esm2022/src/template/pipeline/src/phases/variable_optimization.mjs +0 -423
  181. package/esm2022/src/template/pipeline/src/phases/wrap_icus.mjs +0 -41
  182. package/esm2022/src/template/pipeline/src/util/elements.mjs +0 -29
  183. package/esm2022/src/template_parser/binding_parser.mjs +0 -465
  184. package/esm2022/src/template_parser/template_preparser.mjs +0 -84
  185. package/esm2022/src/util.mjs +0 -124
  186. package/esm2022/src/version.mjs +0 -15
@@ -1,1053 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Google LLC All Rights Reserved.
4
- *
5
- * Use of this source code is governed by an MIT-style license that can be
6
- * found in the LICENSE file at https://angular.io/license
7
- */
8
- /**
9
- * The following set contains all keywords that can be used in the animation css shorthand
10
- * property and is used during the scoping of keyframes to make sure such keywords
11
- * are not modified.
12
- */
13
- const animationKeywords = new Set([
14
- // global values
15
- 'inherit',
16
- 'initial',
17
- 'revert',
18
- 'unset',
19
- // animation-direction
20
- 'alternate',
21
- 'alternate-reverse',
22
- 'normal',
23
- 'reverse',
24
- // animation-fill-mode
25
- 'backwards',
26
- 'both',
27
- 'forwards',
28
- 'none',
29
- // animation-play-state
30
- 'paused',
31
- 'running',
32
- // animation-timing-function
33
- 'ease',
34
- 'ease-in',
35
- 'ease-in-out',
36
- 'ease-out',
37
- 'linear',
38
- 'step-start',
39
- 'step-end',
40
- // `steps()` function
41
- 'end',
42
- 'jump-both',
43
- 'jump-end',
44
- 'jump-none',
45
- 'jump-start',
46
- 'start',
47
- ]);
48
- /**
49
- * The following array contains all of the CSS at-rule identifiers which are scoped.
50
- */
51
- const scopedAtRuleIdentifiers = [
52
- '@media',
53
- '@supports',
54
- '@document',
55
- '@layer',
56
- '@container',
57
- '@scope',
58
- '@starting-style',
59
- ];
60
- /**
61
- * The following class has its origin from a port of shadowCSS from webcomponents.js to TypeScript.
62
- * It has since diverge in many ways to tailor Angular's needs.
63
- *
64
- * Source:
65
- * https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
66
- *
67
- * The original file level comment is reproduced below
68
- */
69
- /*
70
- This is a limited shim for ShadowDOM css styling.
71
- https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
72
-
73
- The intention here is to support only the styling features which can be
74
- relatively simply implemented. The goal is to allow users to avoid the
75
- most obvious pitfalls and do so without compromising performance significantly.
76
- For ShadowDOM styling that's not covered here, a set of best practices
77
- can be provided that should allow users to accomplish more complex styling.
78
-
79
- The following is a list of specific ShadowDOM styling features and a brief
80
- discussion of the approach used to shim.
81
-
82
- Shimmed features:
83
-
84
- * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host
85
- element using the :host rule. To shim this feature, the :host styles are
86
- reformatted and prefixed with a given scope name and promoted to a
87
- document level stylesheet.
88
- For example, given a scope name of .foo, a rule like this:
89
-
90
- :host {
91
- background: red;
92
- }
93
- }
94
-
95
- becomes:
96
-
97
- .foo {
98
- background: red;
99
- }
100
-
101
- * encapsulation: Styles defined within ShadowDOM, apply only to
102
- dom inside the ShadowDOM.
103
- The selectors are scoped by adding an attribute selector suffix to each
104
- simple selector that contains the host element tag name. Each element
105
- in the element's ShadowDOM template is also given the scope attribute.
106
- Thus, these rules match only elements that have the scope attribute.
107
- For example, given a scope name of x-foo, a rule like this:
108
-
109
- div {
110
- font-weight: bold;
111
- }
112
-
113
- becomes:
114
-
115
- div[x-foo] {
116
- font-weight: bold;
117
- }
118
-
119
- Note that elements that are dynamically added to a scope must have the scope
120
- selector added to them manually.
121
-
122
- * upper/lower bound encapsulation: Styles which are defined outside a
123
- shadowRoot should not cross the ShadowDOM boundary and should not apply
124
- inside a shadowRoot.
125
-
126
- This styling behavior is not emulated. Some possible ways to do this that
127
- were rejected due to complexity and/or performance concerns include: (1) reset
128
- every possible property for every possible selector for a given scope name;
129
- (2) re-implement css in javascript.
130
-
131
- As an alternative, users should make sure to use selectors
132
- specific to the scope in which they are working.
133
-
134
- * ::distributed: This behavior is not emulated. It's often not necessary
135
- to style the contents of a specific insertion point and instead, descendants
136
- of the host element can be styled selectively. Users can also create an
137
- extra node around an insertion point and style that node's contents
138
- via descendent selectors. For example, with a shadowRoot like this:
139
-
140
- <style>
141
- ::content(div) {
142
- background: red;
143
- }
144
- </style>
145
- <content></content>
146
-
147
- could become:
148
-
149
- <style>
150
- / *@polyfill .content-container div * /
151
- ::content(div) {
152
- background: red;
153
- }
154
- </style>
155
- <div class="content-container">
156
- <content></content>
157
- </div>
158
-
159
- Note the use of @polyfill in the comment above a ShadowDOM specific style
160
- declaration. This is a directive to the styling shim to use the selector
161
- in comments in lieu of the next selector when running under polyfill.
162
- */
163
- export class ShadowCss {
164
- constructor() {
165
- /**
166
- * Regular expression used to extrapolate the possible keyframes from an
167
- * animation declaration (with possibly multiple animation definitions)
168
- *
169
- * The regular expression can be divided in three parts
170
- * - (^|\s+|,)
171
- * captures how many (if any) leading whitespaces are present or a comma
172
- * - (?:(?:(['"])((?:\\\\|\\\2|(?!\2).)+)\2)|(-?[A-Za-z][\w\-]*))
173
- * captures two different possible keyframes, ones which are quoted or ones which are valid css
174
- * idents (custom properties excluded)
175
- * - (?=[,\s;]|$)
176
- * simply matches the end of the possible keyframe, valid endings are: a comma, a space, a
177
- * semicolon or the end of the string
178
- */
179
- this._animationDeclarationKeyframesRe = /(^|\s+|,)(?:(?:(['"])((?:\\\\|\\\2|(?!\2).)+)\2)|(-?[A-Za-z][\w\-]*))(?=[,\s]|$)/g;
180
- }
181
- /*
182
- * Shim some cssText with the given selector. Returns cssText that can be included in the document
183
- *
184
- * The selector is the attribute added to all elements inside the host,
185
- * The hostSelector is the attribute added to the host itself.
186
- */
187
- shimCssText(cssText, selector, hostSelector = '') {
188
- // **NOTE**: Do not strip comments as this will cause component sourcemaps to break
189
- // due to shift in lines.
190
- // Collect comments and replace them with a placeholder, this is done to avoid complicating
191
- // the rule parsing RegExp and keep it safer.
192
- const comments = [];
193
- cssText = cssText.replace(_commentRe, (m) => {
194
- if (m.match(_commentWithHashRe)) {
195
- comments.push(m);
196
- }
197
- else {
198
- // Replace non hash comments with empty lines.
199
- // This is done so that we do not leak any sensitive data in comments.
200
- const newLinesMatches = m.match(_newLinesRe);
201
- comments.push((newLinesMatches?.join('') ?? '') + '\n');
202
- }
203
- return COMMENT_PLACEHOLDER;
204
- });
205
- cssText = this._insertDirectives(cssText);
206
- const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
207
- // Add back comments at the original position.
208
- let commentIdx = 0;
209
- return scopedCssText.replace(_commentWithHashPlaceHolderRe, () => comments[commentIdx++]);
210
- }
211
- _insertDirectives(cssText) {
212
- cssText = this._insertPolyfillDirectivesInCssText(cssText);
213
- return this._insertPolyfillRulesInCssText(cssText);
214
- }
215
- /**
216
- * Process styles to add scope to keyframes.
217
- *
218
- * Modify both the names of the keyframes defined in the component styles and also the css
219
- * animation rules using them.
220
- *
221
- * Animation rules using keyframes defined elsewhere are not modified to allow for globally
222
- * defined keyframes.
223
- *
224
- * For example, we convert this css:
225
- *
226
- * ```
227
- * .box {
228
- * animation: box-animation 1s forwards;
229
- * }
230
- *
231
- * @keyframes box-animation {
232
- * to {
233
- * background-color: green;
234
- * }
235
- * }
236
- * ```
237
- *
238
- * to this:
239
- *
240
- * ```
241
- * .box {
242
- * animation: scopeName_box-animation 1s forwards;
243
- * }
244
- *
245
- * @keyframes scopeName_box-animation {
246
- * to {
247
- * background-color: green;
248
- * }
249
- * }
250
- * ```
251
- *
252
- * @param cssText the component's css text that needs to be scoped.
253
- * @param scopeSelector the component's scope selector.
254
- *
255
- * @returns the scoped css text.
256
- */
257
- _scopeKeyframesRelatedCss(cssText, scopeSelector) {
258
- const unscopedKeyframesSet = new Set();
259
- const scopedKeyframesCssText = processRules(cssText, (rule) => this._scopeLocalKeyframeDeclarations(rule, scopeSelector, unscopedKeyframesSet));
260
- return processRules(scopedKeyframesCssText, (rule) => this._scopeAnimationRule(rule, scopeSelector, unscopedKeyframesSet));
261
- }
262
- /**
263
- * Scopes local keyframes names, returning the updated css rule and it also
264
- * adds the original keyframe name to a provided set to collect all keyframes names
265
- * so that it can later be used to scope the animation rules.
266
- *
267
- * For example, it takes a rule such as:
268
- *
269
- * ```
270
- * @keyframes box-animation {
271
- * to {
272
- * background-color: green;
273
- * }
274
- * }
275
- * ```
276
- *
277
- * and returns:
278
- *
279
- * ```
280
- * @keyframes scopeName_box-animation {
281
- * to {
282
- * background-color: green;
283
- * }
284
- * }
285
- * ```
286
- * and as a side effect it adds "box-animation" to the `unscopedKeyframesSet` set
287
- *
288
- * @param cssRule the css rule to process.
289
- * @param scopeSelector the component's scope selector.
290
- * @param unscopedKeyframesSet the set of unscoped keyframes names (which can be
291
- * modified as a side effect)
292
- *
293
- * @returns the css rule modified with the scoped keyframes name.
294
- */
295
- _scopeLocalKeyframeDeclarations(rule, scopeSelector, unscopedKeyframesSet) {
296
- return {
297
- ...rule,
298
- selector: rule.selector.replace(/(^@(?:-webkit-)?keyframes(?:\s+))(['"]?)(.+)\2(\s*)$/, (_, start, quote, keyframeName, endSpaces) => {
299
- unscopedKeyframesSet.add(unescapeQuotes(keyframeName, quote));
300
- return `${start}${quote}${scopeSelector}_${keyframeName}${quote}${endSpaces}`;
301
- }),
302
- };
303
- }
304
- /**
305
- * Function used to scope a keyframes name (obtained from an animation declaration)
306
- * using an existing set of unscopedKeyframes names to discern if the scoping needs to be
307
- * performed (keyframes names of keyframes not defined in the component's css need not to be
308
- * scoped).
309
- *
310
- * @param keyframe the keyframes name to check.
311
- * @param scopeSelector the component's scope selector.
312
- * @param unscopedKeyframesSet the set of unscoped keyframes names.
313
- *
314
- * @returns the scoped name of the keyframe, or the original name is the name need not to be
315
- * scoped.
316
- */
317
- _scopeAnimationKeyframe(keyframe, scopeSelector, unscopedKeyframesSet) {
318
- return keyframe.replace(/^(\s*)(['"]?)(.+?)\2(\s*)$/, (_, spaces1, quote, name, spaces2) => {
319
- name = `${unscopedKeyframesSet.has(unescapeQuotes(name, quote)) ? scopeSelector + '_' : ''}${name}`;
320
- return `${spaces1}${quote}${name}${quote}${spaces2}`;
321
- });
322
- }
323
- /**
324
- * Scope an animation rule so that the keyframes mentioned in such rule
325
- * are scoped if defined in the component's css and left untouched otherwise.
326
- *
327
- * It can scope values of both the 'animation' and 'animation-name' properties.
328
- *
329
- * @param rule css rule to scope.
330
- * @param scopeSelector the component's scope selector.
331
- * @param unscopedKeyframesSet the set of unscoped keyframes names.
332
- *
333
- * @returns the updated css rule.
334
- **/
335
- _scopeAnimationRule(rule, scopeSelector, unscopedKeyframesSet) {
336
- let content = rule.content.replace(/((?:^|\s+|;)(?:-webkit-)?animation\s*:\s*),*([^;]+)/g, (_, start, animationDeclarations) => start +
337
- animationDeclarations.replace(this._animationDeclarationKeyframesRe, (original, leadingSpaces, quote = '', quotedName, nonQuotedName) => {
338
- if (quotedName) {
339
- return `${leadingSpaces}${this._scopeAnimationKeyframe(`${quote}${quotedName}${quote}`, scopeSelector, unscopedKeyframesSet)}`;
340
- }
341
- else {
342
- return animationKeywords.has(nonQuotedName)
343
- ? original
344
- : `${leadingSpaces}${this._scopeAnimationKeyframe(nonQuotedName, scopeSelector, unscopedKeyframesSet)}`;
345
- }
346
- }));
347
- content = content.replace(/((?:^|\s+|;)(?:-webkit-)?animation-name(?:\s*):(?:\s*))([^;]+)/g, (_match, start, commaSeparatedKeyframes) => `${start}${commaSeparatedKeyframes
348
- .split(',')
349
- .map((keyframe) => this._scopeAnimationKeyframe(keyframe, scopeSelector, unscopedKeyframesSet))
350
- .join(',')}`);
351
- return { ...rule, content };
352
- }
353
- /*
354
- * Process styles to convert native ShadowDOM rules that will trip
355
- * up the css parser; we rely on decorating the stylesheet with inert rules.
356
- *
357
- * For example, we convert this rule:
358
- *
359
- * polyfill-next-selector { content: ':host menu-item'; }
360
- * ::content menu-item {
361
- *
362
- * to this:
363
- *
364
- * scopeName menu-item {
365
- *
366
- **/
367
- _insertPolyfillDirectivesInCssText(cssText) {
368
- return cssText.replace(_cssContentNextSelectorRe, function (...m) {
369
- return m[2] + '{';
370
- });
371
- }
372
- /*
373
- * Process styles to add rules which will only apply under the polyfill
374
- *
375
- * For example, we convert this rule:
376
- *
377
- * polyfill-rule {
378
- * content: ':host menu-item';
379
- * ...
380
- * }
381
- *
382
- * to this:
383
- *
384
- * scopeName menu-item {...}
385
- *
386
- **/
387
- _insertPolyfillRulesInCssText(cssText) {
388
- return cssText.replace(_cssContentRuleRe, (...m) => {
389
- const rule = m[0].replace(m[1], '').replace(m[2], '');
390
- return m[4] + rule;
391
- });
392
- }
393
- /* Ensure styles are scoped. Pseudo-scoping takes a rule like:
394
- *
395
- * .foo {... }
396
- *
397
- * and converts this to
398
- *
399
- * scopeName .foo { ... }
400
- */
401
- _scopeCssText(cssText, scopeSelector, hostSelector) {
402
- const unscopedRules = this._extractUnscopedRulesFromCssText(cssText);
403
- // replace :host and :host-context -shadowcsshost and -shadowcsshost respectively
404
- cssText = this._insertPolyfillHostInCssText(cssText);
405
- cssText = this._convertColonHost(cssText);
406
- cssText = this._convertColonHostContext(cssText);
407
- cssText = this._convertShadowDOMSelectors(cssText);
408
- if (scopeSelector) {
409
- cssText = this._scopeKeyframesRelatedCss(cssText, scopeSelector);
410
- cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector);
411
- }
412
- cssText = cssText + '\n' + unscopedRules;
413
- return cssText.trim();
414
- }
415
- /*
416
- * Process styles to add rules which will only apply under the polyfill
417
- * and do not process via CSSOM. (CSSOM is destructive to rules on rare
418
- * occasions, e.g. -webkit-calc on Safari.)
419
- * For example, we convert this rule:
420
- *
421
- * @polyfill-unscoped-rule {
422
- * content: 'menu-item';
423
- * ... }
424
- *
425
- * to this:
426
- *
427
- * menu-item {...}
428
- *
429
- **/
430
- _extractUnscopedRulesFromCssText(cssText) {
431
- let r = '';
432
- let m;
433
- _cssContentUnscopedRuleRe.lastIndex = 0;
434
- while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
435
- const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
436
- r += rule + '\n\n';
437
- }
438
- return r;
439
- }
440
- /*
441
- * convert a rule like :host(.foo) > .bar { }
442
- *
443
- * to
444
- *
445
- * .foo<scopeName> > .bar
446
- */
447
- _convertColonHost(cssText) {
448
- return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => {
449
- if (hostSelectors) {
450
- const convertedSelectors = [];
451
- const hostSelectorArray = hostSelectors.split(',').map((p) => p.trim());
452
- for (const hostSelector of hostSelectorArray) {
453
- if (!hostSelector)
454
- break;
455
- const convertedSelector = _polyfillHostNoCombinator + hostSelector.replace(_polyfillHost, '') + otherSelectors;
456
- convertedSelectors.push(convertedSelector);
457
- }
458
- return convertedSelectors.join(',');
459
- }
460
- else {
461
- return _polyfillHostNoCombinator + otherSelectors;
462
- }
463
- });
464
- }
465
- /*
466
- * convert a rule like :host-context(.foo) > .bar { }
467
- *
468
- * to
469
- *
470
- * .foo<scopeName> > .bar, .foo <scopeName> > .bar { }
471
- *
472
- * and
473
- *
474
- * :host-context(.foo:host) .bar { ... }
475
- *
476
- * to
477
- *
478
- * .foo<scopeName> .bar { ... }
479
- */
480
- _convertColonHostContext(cssText) {
481
- return cssText.replace(_cssColonHostContextReGlobal, (selectorText) => {
482
- // We have captured a selector that contains a `:host-context` rule.
483
- // For backward compatibility `:host-context` may contain a comma separated list of selectors.
484
- // Each context selector group will contain a list of host-context selectors that must match
485
- // an ancestor of the host.
486
- // (Normally `contextSelectorGroups` will only contain a single array of context selectors.)
487
- const contextSelectorGroups = [[]];
488
- // There may be more than `:host-context` in this selector so `selectorText` could look like:
489
- // `:host-context(.one):host-context(.two)`.
490
- // Execute `_cssColonHostContextRe` over and over until we have extracted all the
491
- // `:host-context` selectors from this selector.
492
- let match;
493
- while ((match = _cssColonHostContextRe.exec(selectorText))) {
494
- // `match` = [':host-context(<selectors>)<rest>', <selectors>, <rest>]
495
- // The `<selectors>` could actually be a comma separated list: `:host-context(.one, .two)`.
496
- const newContextSelectors = (match[1] ?? '')
497
- .trim()
498
- .split(',')
499
- .map((m) => m.trim())
500
- .filter((m) => m !== '');
501
- // We must duplicate the current selector group for each of these new selectors.
502
- // For example if the current groups are:
503
- // ```
504
- // [
505
- // ['a', 'b', 'c'],
506
- // ['x', 'y', 'z'],
507
- // ]
508
- // ```
509
- // And we have a new set of comma separated selectors: `:host-context(m,n)` then the new
510
- // groups are:
511
- // ```
512
- // [
513
- // ['a', 'b', 'c', 'm'],
514
- // ['x', 'y', 'z', 'm'],
515
- // ['a', 'b', 'c', 'n'],
516
- // ['x', 'y', 'z', 'n'],
517
- // ]
518
- // ```
519
- const contextSelectorGroupsLength = contextSelectorGroups.length;
520
- repeatGroups(contextSelectorGroups, newContextSelectors.length);
521
- for (let i = 0; i < newContextSelectors.length; i++) {
522
- for (let j = 0; j < contextSelectorGroupsLength; j++) {
523
- contextSelectorGroups[j + i * contextSelectorGroupsLength].push(newContextSelectors[i]);
524
- }
525
- }
526
- // Update the `selectorText` and see repeat to see if there are more `:host-context`s.
527
- selectorText = match[2];
528
- }
529
- // The context selectors now must be combined with each other to capture all the possible
530
- // selectors that `:host-context` can match. See `combineHostContextSelectors()` for more
531
- // info about how this is done.
532
- return contextSelectorGroups
533
- .map((contextSelectors) => combineHostContextSelectors(contextSelectors, selectorText))
534
- .join(', ');
535
- });
536
- }
537
- /*
538
- * Convert combinators like ::shadow and pseudo-elements like ::content
539
- * by replacing with space.
540
- */
541
- _convertShadowDOMSelectors(cssText) {
542
- return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText);
543
- }
544
- // change a selector like 'div' to 'name div'
545
- _scopeSelectors(cssText, scopeSelector, hostSelector) {
546
- return processRules(cssText, (rule) => {
547
- let selector = rule.selector;
548
- let content = rule.content;
549
- if (rule.selector[0] !== '@') {
550
- selector = this._scopeSelector(rule.selector, scopeSelector, hostSelector);
551
- }
552
- else if (scopedAtRuleIdentifiers.some((atRule) => rule.selector.startsWith(atRule))) {
553
- content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
554
- }
555
- else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
556
- content = this._stripScopingSelectors(rule.content);
557
- }
558
- return new CssRule(selector, content);
559
- });
560
- }
561
- /**
562
- * Handle a css text that is within a rule that should not contain scope selectors by simply
563
- * removing them! An example of such a rule is `@font-face`.
564
- *
565
- * `@font-face` rules cannot contain nested selectors. Nor can they be nested under a selector.
566
- * Normally this would be a syntax error by the author of the styles. But in some rare cases, such
567
- * as importing styles from a library, and applying `:host ::ng-deep` to the imported styles, we
568
- * can end up with broken css if the imported styles happen to contain @font-face rules.
569
- *
570
- * For example:
571
- *
572
- * ```
573
- * :host ::ng-deep {
574
- * import 'some/lib/containing/font-face';
575
- * }
576
- *
577
- * Similar logic applies to `@page` rules which can contain a particular set of properties,
578
- * as well as some specific at-rules. Since they can't be encapsulated, we have to strip
579
- * any scoping selectors from them. For more information: https://www.w3.org/TR/css-page-3
580
- * ```
581
- */
582
- _stripScopingSelectors(cssText) {
583
- return processRules(cssText, (rule) => {
584
- const selector = rule.selector
585
- .replace(_shadowDeepSelectors, ' ')
586
- .replace(_polyfillHostNoCombinatorRe, ' ');
587
- return new CssRule(selector, rule.content);
588
- });
589
- }
590
- _scopeSelector(selector, scopeSelector, hostSelector) {
591
- return selector
592
- .split(/ ?, ?/)
593
- .map((part) => part.split(_shadowDeepSelectors))
594
- .map((deepParts) => {
595
- const [shallowPart, ...otherParts] = deepParts;
596
- const applyScope = (shallowPart) => {
597
- if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
598
- return this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
599
- }
600
- else {
601
- return shallowPart;
602
- }
603
- };
604
- return [applyScope(shallowPart), ...otherParts].join(' ');
605
- })
606
- .join(', ');
607
- }
608
- _selectorNeedsScoping(selector, scopeSelector) {
609
- const re = this._makeScopeMatcher(scopeSelector);
610
- return !re.test(selector);
611
- }
612
- _makeScopeMatcher(scopeSelector) {
613
- const lre = /\[/g;
614
- const rre = /\]/g;
615
- scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]');
616
- return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
617
- }
618
- // scope via name and [is=name]
619
- _applySimpleSelectorScope(selector, scopeSelector, hostSelector) {
620
- // In Android browser, the lastIndex is not reset when the regex is used in String.replace()
621
- _polyfillHostRe.lastIndex = 0;
622
- if (_polyfillHostRe.test(selector)) {
623
- const replaceBy = `[${hostSelector}]`;
624
- return selector
625
- .replace(_polyfillHostNoCombinatorRe, (hnc, selector) => {
626
- return selector.replace(/([^:]*)(:*)(.*)/, (_, before, colon, after) => {
627
- return before + replaceBy + colon + after;
628
- });
629
- })
630
- .replace(_polyfillHostRe, replaceBy + ' ');
631
- }
632
- return scopeSelector + ' ' + selector;
633
- }
634
- // return a selector with [name] suffix on each simple selector
635
- // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */
636
- _applySelectorScope(selector, scopeSelector, hostSelector) {
637
- const isRe = /\[is=([^\]]*)\]/g;
638
- scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]);
639
- const attrName = '[' + scopeSelector + ']';
640
- const _scopeSelectorPart = (p) => {
641
- let scopedP = p.trim();
642
- if (!scopedP) {
643
- return p;
644
- }
645
- if (p.includes(_polyfillHostNoCombinator)) {
646
- scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
647
- }
648
- else {
649
- // remove :host since it should be unnecessary
650
- const t = p.replace(_polyfillHostRe, '');
651
- if (t.length > 0) {
652
- const matches = t.match(/([^:]*)(:*)(.*)/);
653
- if (matches) {
654
- scopedP = matches[1] + attrName + matches[2] + matches[3];
655
- }
656
- }
657
- }
658
- return scopedP;
659
- };
660
- const safeContent = new SafeSelector(selector);
661
- selector = safeContent.content();
662
- let scopedSelector = '';
663
- let startIndex = 0;
664
- let res;
665
- const sep = /( |>|\+|~(?!=))\s*/g;
666
- // If a selector appears before :host it should not be shimmed as it
667
- // matches on ancestor elements and not on elements in the host's shadow
668
- // `:host-context(div)` is transformed to
669
- // `-shadowcsshost-no-combinatordiv, div -shadowcsshost-no-combinator`
670
- // the `div` is not part of the component in the 2nd selectors and should not be scoped.
671
- // Historically `component-tag:host` was matching the component so we also want to preserve
672
- // this behavior to avoid breaking legacy apps (it should not match).
673
- // The behavior should be:
674
- // - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything)
675
- // - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a
676
- // `:host-context(tag)`)
677
- const hasHost = selector.includes(_polyfillHostNoCombinator);
678
- // Only scope parts after the first `-shadowcsshost-no-combinator` when it is present
679
- let shouldScope = !hasHost;
680
- while ((res = sep.exec(selector)) !== null) {
681
- const separator = res[1];
682
- // Do not trim the selector, as otherwise this will break sourcemaps
683
- // when they are defined on multiple lines
684
- // Example:
685
- // div,
686
- // p { color: red}
687
- const part = selector.slice(startIndex, res.index);
688
- // A space following an escaped hex value and followed by another hex character
689
- // (ie: ".\fc ber" for ".über") is not a separator between 2 selectors
690
- // also keep in mind that backslashes are replaced by a placeholder by SafeSelector
691
- // These escaped selectors happen for example when esbuild runs with optimization.minify.
692
- if (part.match(/__esc-ph-(\d+)__/) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
693
- continue;
694
- }
695
- shouldScope = shouldScope || part.includes(_polyfillHostNoCombinator);
696
- const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
697
- scopedSelector += `${scopedPart} ${separator} `;
698
- startIndex = sep.lastIndex;
699
- }
700
- const part = selector.substring(startIndex);
701
- shouldScope = shouldScope || part.includes(_polyfillHostNoCombinator);
702
- scopedSelector += shouldScope ? _scopeSelectorPart(part) : part;
703
- // replace the placeholders with their original values
704
- return safeContent.restore(scopedSelector);
705
- }
706
- _insertPolyfillHostInCssText(selector) {
707
- return selector
708
- .replace(_colonHostContextRe, _polyfillHostContext)
709
- .replace(_colonHostRe, _polyfillHost);
710
- }
711
- }
712
- class SafeSelector {
713
- constructor(selector) {
714
- this.placeholders = [];
715
- this.index = 0;
716
- // Replaces attribute selectors with placeholders.
717
- // The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
718
- selector = this._escapeRegexMatches(selector, /(\[[^\]]*\])/g);
719
- // CSS allows for certain special characters to be used in selectors if they're escaped.
720
- // E.g. `.foo:blue` won't match a class called `foo:blue`, because the colon denotes a
721
- // pseudo-class, but writing `.foo\:blue` will match, because the colon was escaped.
722
- // Replace all escape sequences (`\` followed by a character) with a placeholder so
723
- // that our handling of pseudo-selectors doesn't mess with them.
724
- // Escaped characters have a specific placeholder so they can be detected separately.
725
- selector = selector.replace(/(\\.)/g, (_, keep) => {
726
- const replaceBy = `__esc-ph-${this.index}__`;
727
- this.placeholders.push(keep);
728
- this.index++;
729
- return replaceBy;
730
- });
731
- // Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
732
- // WS and "+" would otherwise be interpreted as selector separators.
733
- this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
734
- const replaceBy = `__ph-${this.index}__`;
735
- this.placeholders.push(exp);
736
- this.index++;
737
- return pseudo + replaceBy;
738
- });
739
- }
740
- restore(content) {
741
- return content.replace(/__(?:ph|esc-ph)-(\d+)__/g, (_ph, index) => this.placeholders[+index]);
742
- }
743
- content() {
744
- return this._content;
745
- }
746
- /**
747
- * Replaces all of the substrings that match a regex within a
748
- * special string (e.g. `__ph-0__`, `__ph-1__`, etc).
749
- */
750
- _escapeRegexMatches(content, pattern) {
751
- return content.replace(pattern, (_, keep) => {
752
- const replaceBy = `__ph-${this.index}__`;
753
- this.placeholders.push(keep);
754
- this.index++;
755
- return replaceBy;
756
- });
757
- }
758
- }
759
- const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim;
760
- const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
761
- const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
762
- const _polyfillHost = '-shadowcsshost';
763
- // note: :host-context pre-processed to -shadowcsshostcontext.
764
- const _polyfillHostContext = '-shadowcsscontext';
765
- const _parenSuffix = '(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))?([^,{]*)';
766
- const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix, 'gim');
767
- const _cssColonHostContextReGlobal = new RegExp(_polyfillHostContext + _parenSuffix, 'gim');
768
- const _cssColonHostContextRe = new RegExp(_polyfillHostContext + _parenSuffix, 'im');
769
- const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
770
- const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
771
- const _shadowDOMSelectorsRe = [
772
- /::shadow/g,
773
- /::content/g,
774
- // Deprecated selectors
775
- /\/shadow-deep\//g,
776
- /\/shadow\//g,
777
- ];
778
- // The deep combinator is deprecated in the CSS spec
779
- // Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
780
- // see https://github.com/angular/angular/pull/17677
781
- const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
782
- const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$';
783
- const _polyfillHostRe = /-shadowcsshost/gim;
784
- const _colonHostRe = /:host/gim;
785
- const _colonHostContextRe = /:host-context/gim;
786
- const _newLinesRe = /\r?\n/g;
787
- const _commentRe = /\/\*[\s\S]*?\*\//g;
788
- const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=/g;
789
- const COMMENT_PLACEHOLDER = '%COMMENT%';
790
- const _commentWithHashPlaceHolderRe = new RegExp(COMMENT_PLACEHOLDER, 'g');
791
- const BLOCK_PLACEHOLDER = '%BLOCK%';
792
- const _ruleRe = new RegExp(`(\\s*(?:${COMMENT_PLACEHOLDER}\\s*)*)([^;\\{\\}]+?)(\\s*)((?:{%BLOCK%}?\\s*;?)|(?:\\s*;))`, 'g');
793
- const CONTENT_PAIRS = new Map([['{', '}']]);
794
- const COMMA_IN_PLACEHOLDER = '%COMMA_IN_PLACEHOLDER%';
795
- const SEMI_IN_PLACEHOLDER = '%SEMI_IN_PLACEHOLDER%';
796
- const COLON_IN_PLACEHOLDER = '%COLON_IN_PLACEHOLDER%';
797
- const _cssCommaInPlaceholderReGlobal = new RegExp(COMMA_IN_PLACEHOLDER, 'g');
798
- const _cssSemiInPlaceholderReGlobal = new RegExp(SEMI_IN_PLACEHOLDER, 'g');
799
- const _cssColonInPlaceholderReGlobal = new RegExp(COLON_IN_PLACEHOLDER, 'g');
800
- export class CssRule {
801
- constructor(selector, content) {
802
- this.selector = selector;
803
- this.content = content;
804
- }
805
- }
806
- export function processRules(input, ruleCallback) {
807
- const escaped = escapeInStrings(input);
808
- const inputWithEscapedBlocks = escapeBlocks(escaped, CONTENT_PAIRS, BLOCK_PLACEHOLDER);
809
- let nextBlockIndex = 0;
810
- const escapedResult = inputWithEscapedBlocks.escapedString.replace(_ruleRe, (...m) => {
811
- const selector = m[2];
812
- let content = '';
813
- let suffix = m[4];
814
- let contentPrefix = '';
815
- if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) {
816
- content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
817
- suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1);
818
- contentPrefix = '{';
819
- }
820
- const rule = ruleCallback(new CssRule(selector, content));
821
- return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
822
- });
823
- return unescapeInStrings(escapedResult);
824
- }
825
- class StringWithEscapedBlocks {
826
- constructor(escapedString, blocks) {
827
- this.escapedString = escapedString;
828
- this.blocks = blocks;
829
- }
830
- }
831
- function escapeBlocks(input, charPairs, placeholder) {
832
- const resultParts = [];
833
- const escapedBlocks = [];
834
- let openCharCount = 0;
835
- let nonBlockStartIndex = 0;
836
- let blockStartIndex = -1;
837
- let openChar;
838
- let closeChar;
839
- for (let i = 0; i < input.length; i++) {
840
- const char = input[i];
841
- if (char === '\\') {
842
- i++;
843
- }
844
- else if (char === closeChar) {
845
- openCharCount--;
846
- if (openCharCount === 0) {
847
- escapedBlocks.push(input.substring(blockStartIndex, i));
848
- resultParts.push(placeholder);
849
- nonBlockStartIndex = i;
850
- blockStartIndex = -1;
851
- openChar = closeChar = undefined;
852
- }
853
- }
854
- else if (char === openChar) {
855
- openCharCount++;
856
- }
857
- else if (openCharCount === 0 && charPairs.has(char)) {
858
- openChar = char;
859
- closeChar = charPairs.get(char);
860
- openCharCount = 1;
861
- blockStartIndex = i + 1;
862
- resultParts.push(input.substring(nonBlockStartIndex, blockStartIndex));
863
- }
864
- }
865
- if (blockStartIndex !== -1) {
866
- escapedBlocks.push(input.substring(blockStartIndex));
867
- resultParts.push(placeholder);
868
- }
869
- else {
870
- resultParts.push(input.substring(nonBlockStartIndex));
871
- }
872
- return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
873
- }
874
- /**
875
- * Object containing as keys characters that should be substituted by placeholders
876
- * when found in strings during the css text parsing, and as values the respective
877
- * placeholders
878
- */
879
- const ESCAPE_IN_STRING_MAP = {
880
- ';': SEMI_IN_PLACEHOLDER,
881
- ',': COMMA_IN_PLACEHOLDER,
882
- ':': COLON_IN_PLACEHOLDER,
883
- };
884
- /**
885
- * Parse the provided css text and inside strings (meaning, inside pairs of unescaped single or
886
- * double quotes) replace specific characters with their respective placeholders as indicated
887
- * by the `ESCAPE_IN_STRING_MAP` map.
888
- *
889
- * For example convert the text
890
- * `animation: "my-anim:at\"ion" 1s;`
891
- * to
892
- * `animation: "my-anim%COLON_IN_PLACEHOLDER%at\"ion" 1s;`
893
- *
894
- * This is necessary in order to remove the meaning of some characters when found inside strings
895
- * (for example `;` indicates the end of a css declaration, `,` the sequence of values and `:` the
896
- * division between property and value during a declaration, none of these meanings apply when such
897
- * characters are within strings and so in order to prevent parsing issues they need to be replaced
898
- * with placeholder text for the duration of the css manipulation process).
899
- *
900
- * @param input the original css text.
901
- *
902
- * @returns the css text with specific characters in strings replaced by placeholders.
903
- **/
904
- function escapeInStrings(input) {
905
- let result = input;
906
- let currentQuoteChar = null;
907
- for (let i = 0; i < result.length; i++) {
908
- const char = result[i];
909
- if (char === '\\') {
910
- i++;
911
- }
912
- else {
913
- if (currentQuoteChar !== null) {
914
- // index i is inside a quoted sub-string
915
- if (char === currentQuoteChar) {
916
- currentQuoteChar = null;
917
- }
918
- else {
919
- const placeholder = ESCAPE_IN_STRING_MAP[char];
920
- if (placeholder) {
921
- result = `${result.substr(0, i)}${placeholder}${result.substr(i + 1)}`;
922
- i += placeholder.length - 1;
923
- }
924
- }
925
- }
926
- else if (char === "'" || char === '"') {
927
- currentQuoteChar = char;
928
- }
929
- }
930
- }
931
- return result;
932
- }
933
- /**
934
- * Replace in a string all occurrences of keys in the `ESCAPE_IN_STRING_MAP` map with their
935
- * original representation, this is simply used to revert the changes applied by the
936
- * escapeInStrings function.
937
- *
938
- * For example it reverts the text:
939
- * `animation: "my-anim%COLON_IN_PLACEHOLDER%at\"ion" 1s;`
940
- * to it's original form of:
941
- * `animation: "my-anim:at\"ion" 1s;`
942
- *
943
- * Note: For the sake of simplicity this function does not check that the placeholders are
944
- * actually inside strings as it would anyway be extremely unlikely to find them outside of strings.
945
- *
946
- * @param input the css text containing the placeholders.
947
- *
948
- * @returns the css text without the placeholders.
949
- */
950
- function unescapeInStrings(input) {
951
- let result = input.replace(_cssCommaInPlaceholderReGlobal, ',');
952
- result = result.replace(_cssSemiInPlaceholderReGlobal, ';');
953
- result = result.replace(_cssColonInPlaceholderReGlobal, ':');
954
- return result;
955
- }
956
- /**
957
- * Unescape all quotes present in a string, but only if the string was actually already
958
- * quoted.
959
- *
960
- * This generates a "canonical" representation of strings which can be used to match strings
961
- * which would otherwise only differ because of differently escaped quotes.
962
- *
963
- * For example it converts the string (assumed to be quoted):
964
- * `this \\"is\\" a \\'\\\\'test`
965
- * to:
966
- * `this "is" a '\\\\'test`
967
- * (note that the latter backslashes are not removed as they are not actually escaping the single
968
- * quote)
969
- *
970
- *
971
- * @param input the string possibly containing escaped quotes.
972
- * @param isQuoted boolean indicating whether the string was quoted inside a bigger string (if not
973
- * then it means that it doesn't represent an inner string and thus no unescaping is required)
974
- *
975
- * @returns the string in the "canonical" representation without escaped quotes.
976
- */
977
- function unescapeQuotes(str, isQuoted) {
978
- return !isQuoted ? str : str.replace(/((?:^|[^\\])(?:\\\\)*)\\(?=['"])/g, '$1');
979
- }
980
- /**
981
- * Combine the `contextSelectors` with the `hostMarker` and the `otherSelectors`
982
- * to create a selector that matches the same as `:host-context()`.
983
- *
984
- * Given a single context selector `A` we need to output selectors that match on the host and as an
985
- * ancestor of the host:
986
- *
987
- * ```
988
- * A <hostMarker>, A<hostMarker> {}
989
- * ```
990
- *
991
- * When there is more than one context selector we also have to create combinations of those
992
- * selectors with each other. For example if there are `A` and `B` selectors the output is:
993
- *
994
- * ```
995
- * AB<hostMarker>, AB <hostMarker>, A B<hostMarker>,
996
- * B A<hostMarker>, A B <hostMarker>, B A <hostMarker> {}
997
- * ```
998
- *
999
- * And so on...
1000
- *
1001
- * @param contextSelectors an array of context selectors that will be combined.
1002
- * @param otherSelectors the rest of the selectors that are not context selectors.
1003
- */
1004
- function combineHostContextSelectors(contextSelectors, otherSelectors) {
1005
- const hostMarker = _polyfillHostNoCombinator;
1006
- _polyfillHostRe.lastIndex = 0; // reset the regex to ensure we get an accurate test
1007
- const otherSelectorsHasHost = _polyfillHostRe.test(otherSelectors);
1008
- // If there are no context selectors then just output a host marker
1009
- if (contextSelectors.length === 0) {
1010
- return hostMarker + otherSelectors;
1011
- }
1012
- const combined = [contextSelectors.pop() || ''];
1013
- while (contextSelectors.length > 0) {
1014
- const length = combined.length;
1015
- const contextSelector = contextSelectors.pop();
1016
- for (let i = 0; i < length; i++) {
1017
- const previousSelectors = combined[i];
1018
- // Add the new selector as a descendant of the previous selectors
1019
- combined[length * 2 + i] = previousSelectors + ' ' + contextSelector;
1020
- // Add the new selector as an ancestor of the previous selectors
1021
- combined[length + i] = contextSelector + ' ' + previousSelectors;
1022
- // Add the new selector to act on the same element as the previous selectors
1023
- combined[i] = contextSelector + previousSelectors;
1024
- }
1025
- }
1026
- // Finally connect the selector to the `hostMarker`s: either acting directly on the host
1027
- // (A<hostMarker>) or as an ancestor (A <hostMarker>).
1028
- return combined
1029
- .map((s) => otherSelectorsHasHost
1030
- ? `${s}${otherSelectors}`
1031
- : `${s}${hostMarker}${otherSelectors}, ${s} ${hostMarker}${otherSelectors}`)
1032
- .join(',');
1033
- }
1034
- /**
1035
- * Mutate the given `groups` array so that there are `multiples` clones of the original array
1036
- * stored.
1037
- *
1038
- * For example `repeatGroups([a, b], 3)` will result in `[a, b, a, b, a, b]` - but importantly the
1039
- * newly added groups will be clones of the original.
1040
- *
1041
- * @param groups An array of groups of strings that will be repeated. This array is mutated
1042
- * in-place.
1043
- * @param multiples The number of times the current groups should appear.
1044
- */
1045
- export function repeatGroups(groups, multiples) {
1046
- const length = groups.length;
1047
- for (let i = 1; i < multiples; i++) {
1048
- for (let j = 0; j < length; j++) {
1049
- groups[j + i * length] = groups[j].slice(0);
1050
- }
1051
- }
1052
- }
1053
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhZG93X2Nzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9zaGFkb3dfY3NzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVIOzs7O0dBSUc7QUFDSCxNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxDQUFDO0lBQ2hDLGdCQUFnQjtJQUNoQixTQUFTO0lBQ1QsU0FBUztJQUNULFFBQVE7SUFDUixPQUFPO0lBQ1Asc0JBQXNCO0lBQ3RCLFdBQVc7SUFDWCxtQkFBbUI7SUFDbkIsUUFBUTtJQUNSLFNBQVM7SUFDVCxzQkFBc0I7SUFDdEIsV0FBVztJQUNYLE1BQU07SUFDTixVQUFVO0lBQ1YsTUFBTTtJQUNOLHVCQUF1QjtJQUN2QixRQUFRO0lBQ1IsU0FBUztJQUNULDRCQUE0QjtJQUM1QixNQUFNO0lBQ04sU0FBUztJQUNULGFBQWE7SUFDYixVQUFVO0lBQ1YsUUFBUTtJQUNSLFlBQVk7SUFDWixVQUFVO0lBQ1YscUJBQXFCO0lBQ3JCLEtBQUs7SUFDTCxXQUFXO0lBQ1gsVUFBVTtJQUNWLFdBQVc7SUFDWCxZQUFZO0lBQ1osT0FBTztDQUNSLENBQUMsQ0FBQztBQUVIOztHQUVHO0FBQ0gsTUFBTSx1QkFBdUIsR0FBRztJQUM5QixRQUFRO0lBQ1IsV0FBVztJQUNYLFdBQVc7SUFDWCxRQUFRO0lBQ1IsWUFBWTtJQUNaLFFBQVE7SUFDUixpQkFBaUI7Q0FDbEIsQ0FBQztBQUVGOzs7Ozs7OztHQVFHO0FBRUg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQTZGRTtBQUNGLE1BQU0sT0FBTyxTQUFTO0lBQXRCO1FBcUtFOzs7Ozs7Ozs7Ozs7O1dBYUc7UUFDSyxxQ0FBZ0MsR0FDdEMsbUZBQW1GLENBQUM7SUE2Y3hGLENB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SUFDaEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM3QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDbkMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2hDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUMsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbi8qKlxuICogVGhlIGZvbGxvd2luZyBzZXQgY29udGFpbnMgYWxsIGtleXdvcmRzIHRoYXQgY2FuIGJlIHVzZWQgaW4gdGhlIGFuaW1hdGlvbiBjc3Mgc2hvcnRoYW5kXG4gKiBwcm9wZXJ0eSBhbmQgaXMgdXNlZCBkdXJpbmcgdGhlIHNjb3Bpbmcgb2Yga2V5ZnJhbWVzIHRvIG1ha2Ugc3VyZSBzdWNoIGtleXdvcmRzXG4gKiBhcmUgbm90IG1vZGlmaWVkLlxuICovXG5jb25zdCBhbmltYXRpb25LZXl3b3JkcyA9IG5ldyBTZXQoW1xuICAvLyBnbG9iYWwgdmFsdWVzXG4gICdpbmhlcml0JyxcbiAgJ2luaXRpYWwnLFxuICAncmV2ZXJ0JyxcbiAgJ3Vuc2V0JyxcbiAgLy8gYW5pbWF0aW9uLWRpcmVjdGlvblxuICAnYWx0ZXJuYXRlJyxcbiAgJ2FsdGVybmF0ZS1yZXZlcnNlJyxcbiAgJ25vcm1hbCcsXG4gICdyZXZlcnNlJyxcbiAgLy8gYW5pbWF0aW9uLWZpbGwtbW9kZVxuICAnYmFja3dhcmRzJyxcbiAgJ2JvdGgnLFxuICAnZm9yd2FyZHMnLFxuICAnbm9uZScsXG4gIC8vIGFuaW1hdGlvbi1wbGF5LXN0YXRlXG4gICdwYXVzZWQnLFxuICAncnVubmluZycsXG4gIC8vIGFuaW1hdGlvbi10aW1pbmctZnVuY3Rpb25cbiAgJ2Vhc2UnLFxuICAnZWFzZS1pbicsXG4gICdlYXNlLWluLW91dCcsXG4gICdlYXNlLW91dCcsXG4gICdsaW5lYXInLFxuICAnc3RlcC1zdGFydCcsXG4gICdzdGVwLWVuZCcsXG4gIC8vIGBzdGVwcygpYCBmdW5jdGlvblxuICAnZW5kJyxcbiAgJ2p1bXAtYm90aCcsXG4gICdqdW1wLWVuZCcsXG4gICdqdW1wLW5vbmUnLFxuICAnanVtcC1zdGFydCcsXG4gICdzdGFydCcsXG5dKTtcblxuLyoqXG4gKiBUaGUgZm9sbG93aW5nIGFycmF5IGNvbnRhaW5zIGFsbCBvZiB0aGUgQ1NTIGF0LXJ1bGUgaWRlbnRpZmllcnMgd2hpY2ggYXJlIHNjb3BlZC5cbiAqL1xuY29uc3Qgc2NvcGVkQXRSdWxlSWRlbnRpZmllcnMgPSBbXG4gICdAbWVkaWEnLFxuICAnQHN1cHBvcnRzJyxcbiAgJ0Bkb2N1bWVudCcsXG4gICdAbGF5ZXInLFxuICAnQGNvbnRhaW5lcicsXG4gICdAc2NvcGUnLFxuICAnQHN0YXJ0aW5nLXN0eWxlJyxcbl07XG5cbi8qKlxuICogVGhlIGZvbGxvd2luZyBjbGFzcyBoYXMgaXRzIG9yaWdpbiBmcm9tIGEgcG9ydCBvZiBzaGFkb3dDU1MgZnJvbSB3ZWJjb21wb25lbnRzLmpzIHRvIFR5cGVTY3JpcHQuXG4gKiBJdCBoYXMgc2luY2UgZGl2ZXJnZSBpbiBtYW55IHdheXMgdG8gdGFpbG9yIEFuZ3VsYXIncyBuZWVkcy5cbiAqXG4gKiBTb3VyY2U6XG4gKiBodHRwczovL2dpdGh1Yi5jb20vd2ViY29tcG9uZW50cy93ZWJjb21wb25lbnRzanMvYmxvYi80ZWZlY2Q3ZTBlL3NyYy9TaGFkb3dDU1MvU2hhZG93Q1NTLmpzXG4gKlxuICogVGhlIG9yaWdpbmFsIGZpbGUgbGV2ZWwgY29tbWVudCBpcyByZXByb2R1Y2VkIGJlbG93XG4gKi9cblxuLypcbiAgVGhpcyBpcyBhIGxpbWl0ZWQgc2hpbSBmb3IgU2hhZG93RE9NIGNzcyBzdHlsaW5nLlxuICBodHRwczovL2R2Y3MudzMub3JnL2hnL3dlYmNvbXBvbmVudHMvcmF3LWZpbGUvdGlwL3NwZWMvc2hhZG93L2luZGV4Lmh0bWwjc3R5bGVzXG5cbiAgVGhlIGludGVudGlvbiBoZXJlIGlzIHRvIHN1cHBvcnQgb25seSB0aGUgc3R5bGluZyBmZWF0dXJlcyB3aGljaCBjYW4gYmVcbiAgcmVsYXRpdmVseSBzaW1wbHkgaW1wbGVtZW50ZWQuIFRoZSBnb2FsIGlzIHRvIGFsbG93IHVzZXJzIHRvIGF2b2lkIHRoZVxuICBtb3N0IG9idmlvdXMgcGl0ZmFsbHMgYW5kIGRvIHNvIHdpdGhvdXQgY29tcHJvbWlzaW5nIHBlcmZvcm1hbmNlIHNpZ25pZmljYW50bHkuXG4gIEZvciBTaGFkb3dET00gc3R5bGluZyB0aGF0J3Mgbm90IGNvdmVyZWQgaGVyZSwgYSBzZXQgb2YgYmVzdCBwcmFjdGljZXNcbiAgY2FuIGJlIHByb3ZpZGVkIHRoYXQgc2hvdWxkIGFsbG93IHVzZXJzIHRvIGFjY29tcGxpc2ggbW9yZSBjb21wbGV4IHN0eWxpbmcuXG5cbiAgVGhlIGZvbGxvd2luZyBpcyBhIGxpc3Qgb2Ygc3BlY2lmaWMgU2hhZG93RE9NIHN0eWxpbmcgZmVhdHVyZXMgYW5kIGEgYnJpZWZcbiAgZGlzY3Vzc2lvbiBvZiB0aGUgYXBwcm9hY2ggdXNlZCB0byBzaGltLlxuXG4gIFNoaW1tZWQgZmVhdHVyZXM6XG5cbiAgKiA6aG9zdCwgOmhvc3QtY29udGV4dDogU2hhZG93RE9NIGFsbG93cyBzdHlsaW5nIG9mIHRoZSBzaGFkb3dSb290J3MgaG9zdFxuICBlbGVtZW50IHVzaW5nIHRoZSA6aG9zdCBydWxlLiBUbyBzaGltIHRoaXMgZmVhdHVyZSwgdGhlIDpob3N0IHN0eWxlcyBhcmVcbiAgcmVmb3JtYXR0ZWQgYW5kIHByZWZpeGVkIHdpdGggYSBnaXZlbiBzY29wZSBuYW1lIGFuZCBwcm9tb3RlZCB0byBhXG4gIGRvY3VtZW50IGxldmVsIHN0eWxlc2hlZXQuXG4gIEZvciBleGFtcGxlLCBnaXZlbiBhIHNjb3BlIG5hbWUgb2YgLmZvbywgYSBydWxlIGxpa2UgdGhpczpcblxuICAgIDpob3N0IHtcbiAgICAgICAgYmFja2dyb3VuZDogcmVkO1xuICAgICAgfVxuICAgIH1cblxuICBiZWNvbWVzOlxuXG4gICAgLmZvbyB7XG4gICAgICBiYWNrZ3JvdW5kOiByZWQ7XG4gICAgfVxuXG4gICogZW5jYXBzdWxhdGlvbjogU3R5bGVzIGRlZmluZWQgd2l0aGluIFNoYWRvd0RPTSwgYXBwbHkgb25seSB0b1xuICBkb20gaW5zaWRlIHRoZSBTaGFkb3dET00uXG4gIFRoZSBzZWxlY3RvcnMgYXJlIHNjb3BlZCBieSBhZGRpbmcgYW4gYXR0cmlidXRlIHNlbGVjdG9yIHN1ZmZpeCB0byBlYWNoXG4gIHNpbXBsZSBzZWxlY3RvciB0aGF0IGNvbnRhaW5zIHRoZSBob3N0IGVsZW1lbnQgdGFnIG5hbWUuIEVhY2ggZWxlbWVudFxuICBpbiB0aGUgZWxlbWVudCdzIFNoYWRvd0RPTSB0ZW1wbGF0ZSBpcyBhbHNvIGdpdmVuIHRoZSBzY29wZSBhdHRyaWJ1dGUuXG4gIFRodXMsIHRoZXNlIHJ1bGVzIG1hdGNoIG9ubHkgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBzY29wZSBhdHRyaWJ1dGUuXG4gIEZvciBleGFtcGxlLCBnaXZlbiBhIHNjb3BlIG5hbWUgb2YgeC1mb28sIGEgcnVsZSBsaWtlIHRoaXM6XG5cbiAgICBkaXYge1xuICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XG4gICAgfVxuXG4gIGJlY29tZXM6XG5cbiAgICBkaXZbeC1mb29dIHtcbiAgICAgIGZvbnQtd2VpZ2h0OiBib2xkO1xuICAgIH1cblxuICBOb3RlIHRoYXQgZWxlbWVudHMgdGhhdCBhcmUgZHluYW1pY2FsbHkgYWRkZWQgdG8gYSBzY29wZSBtdXN0IGhhdmUgdGhlIHNjb3BlXG4gIHNlbGVjdG9yIGFkZGVkIHRvIHRoZW0gbWFudWFsbHkuXG5cbiAgKiB1cHBlci9sb3dlciBib3VuZCBlbmNhcHN1bGF0aW9uOiBTdHlsZXMgd2hpY2ggYXJlIGRlZmluZWQgb3V0c2lkZSBhXG4gIHNoYWRvd1Jvb3Qgc2hvdWxkIG5vdCBjcm9zcyB0aGUgU2hhZG93RE9NIGJvdW5kYXJ5IGFuZCBzaG91bGQgbm90IGFwcGx5XG4gIGluc2lkZSBhIHNoYWRvd1Jvb3QuXG5cbiAgVGhpcyBzdHlsaW5nIGJlaGF2aW9yIGlzIG5vdCBlbXVsYXRlZC4gU29tZSBwb3NzaWJsZSB3YXlzIHRvIGRvIHRoaXMgdGhhdFxuICB3ZXJlIHJlamVjdGVkIGR1ZSB0byBjb21wbGV4aXR5IGFuZC9vciBwZXJmb3JtYW5jZSBjb25jZXJucyBpbmNsdWRlOiAoMSkgcmVzZXRcbiAgZXZlcnkgcG9zc2libGUgcHJvcGVydHkgZm9yIGV2ZXJ5IHBvc3NpYmxlIHNlbGVjdG9yIGZvciBhIGdpdmVuIHNjb3BlIG5hbWU7XG4gICgyKSByZS1pbXBsZW1lbnQgY3NzIGluIGphdmFzY3JpcHQuXG5cbiAgQXMgYW4gYWx0ZXJuYXRpdmUsIHVzZXJzIHNob3VsZCBtYWtlIHN1cmUgdG8gdXNlIHNlbGVjdG9yc1xuICBzcGVjaWZpYyB0byB0aGUgc2NvcGUgaW4gd2hpY2ggdGhleSBhcmUgd29ya2luZy5cblxuICAqIDo6ZGlzdHJpYnV0ZWQ6IFRoaXMgYmVoYXZpb3IgaXMgbm90IGVtdWxhdGVkLiBJdCdzIG9mdGVuIG5vdCBuZWNlc3NhcnlcbiAgdG8gc3R5bGUgdGhlIGNvbnRlbnRzIG9mIGEgc3BlY2lmaWMgaW5zZXJ0aW9uIHBvaW50IGFuZCBpbnN0ZWFkLCBkZXNjZW5kYW50c1xuICBvZiB0aGUgaG9zdCBlbGVtZW50IGNhbiBiZSBzdHlsZWQgc2VsZWN0aXZlbHkuIFVzZXJzIGNhbiBhbHNvIGNyZWF0ZSBhblxuICBleHRyYSBub2RlIGFyb3VuZCBhbiBpbnNlcnRpb24gcG9pbnQgYW5kIHN0eWxlIHRoYXQgbm9kZSdzIGNvbnRlbnRzXG4gIHZpYSBkZXNjZW5kZW50IHNlbGVjdG9ycy4gRm9yIGV4YW1wbGUsIHdpdGggYSBzaGFkb3dSb290IGxpa2UgdGhpczpcblxuICAgIDxzdHlsZT5cbiAgICAgIDo6Y29udGVudChkaXYpIHtcbiAgICAgICAgYmFja2dyb3VuZDogcmVkO1xuICAgICAgfVxuICAgIDwvc3R5bGU+XG4gICAgPGNvbnRlbnQ+PC9jb250ZW50PlxuXG4gIGNvdWxkIGJlY29tZTpcblxuICAgIDxzdHlsZT5cbiAgICAgIC8gKkBwb2x5ZmlsbCAuY29udGVudC1jb250YWluZXIgZGl2ICogL1xuICAgICAgOjpjb250ZW50KGRpdikge1xuICAgICAgICBiYWNrZ3JvdW5kOiByZWQ7XG4gICAgICB9XG4gICAgPC9zdHlsZT5cbiAgICA8ZGl2IGNsYXNzPVwiY29udGVudC1jb250YWluZXJcIj5cbiAgICAgIDxjb250ZW50PjwvY29udGVudD5cbiAgICA8L2Rpdj5cblxuICBOb3RlIHRoZSB1c2Ugb2YgQHBvbHlmaWxsIGluIHRoZSBjb21tZW50IGFib3ZlIGEgU2hhZG93RE9NIHNwZWNpZmljIHN0eWxlXG4gIGRlY2xhcmF0aW9uLiBUaGlzIGlzIGEgZGlyZWN0aXZlIHRvIHRoZSBzdHlsaW5nIHNoaW0gdG8gdXNlIHRoZSBzZWxlY3RvclxuICBpbiBjb21tZW50cyBpbiBsaWV1IG9mIHRoZSBuZXh0IHNlbGVjdG9yIHdoZW4gcnVubmluZyB1bmRlciBwb2x5ZmlsbC5cbiovXG5leHBvcnQgY2xhc3MgU2hhZG93Q3NzIHtcbiAgLypcbiAgICogU2hpbSBzb21lIGNzc1RleHQgd2l0aCB0aGUgZ2l2ZW4gc2VsZWN0b3IuIFJldHVybnMgY3NzVGV4dCB0aGF0IGNhbiBiZSBpbmNsdWRlZCBpbiB0aGUgZG9jdW1lbnRcbiAgICpcbiAgICogVGhlIHNlbGVjdG9yIGlzIHRoZSBhdHRyaWJ1dGUgYWRkZWQgdG8gYWxsIGVsZW1lbnRzIGluc2lkZSB0aGUgaG9zdCxcbiAgICogVGhlIGhvc3RTZWxlY3RvciBpcyB0aGUgYXR0cmlidXRlIGFkZGVkIHRvIHRoZSBob3N0IGl0c2VsZi5cbiAgICovXG4gIHNoaW1Dc3NUZXh0KGNzc1RleHQ6IHN0cmluZywgc2VsZWN0b3I6IHN0cmluZywgaG9zdFNlbGVjdG9yOiBzdHJpbmcgPSAnJyk6IHN0cmluZyB7XG4gICAgLy8gKipOT1RFKio6IERvIG5vdCBzdHJpcCBjb21tZW50cyBhcyB0aGlzIHdpbGwgY2F1c2UgY29tcG9uZW50IHNvdXJjZW1hcHMgdG8gYnJlYWtcbiAgICAvLyBkdWUgdG8gc2hpZnQgaW4gbGluZXMuXG5cbiAgICAvLyBDb2xsZWN0IGNvbW1lbnRzIGFuZCByZXBsYWNlIHRoZW0gd2l0aCBhIHBsYWNlaG9sZGVyLCB0aGlzIGlzIGRvbmUgdG8gYXZvaWQgY29tcGxpY2F0aW5nXG4gICAgLy8gdGhlIHJ1bGUgcGFyc2luZyBSZWdFeHAgYW5kIGtlZXAgaXQgc2FmZXIuXG4gICAgY29uc3QgY29tbWVudHM6IHN0cmluZ1tdID0gW107XG4gICAgY3NzVGV4dCA9IGNzc1RleHQucmVwbGFjZShfY29tbWVudFJlLCAobSkgPT4ge1xuICAgICAgaWYgKG0ubWF0Y2goX2NvbW1lbnRXaXRoSGFzaFJlKSkge1xuICAgICAgICBjb21tZW50cy5wdXNoKG0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmVwbGFjZSBub24gaGFzaCBjb21tZW50cyB3aXRoIGVtcHR5IGxpbmVzLlxuICAgICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB3ZSBkbyBub3QgbGVhayBhbnkgc2Vuc2l0aXZlIGRhdGEgaW4gY29tbWVudHMuXG4gICAgICAgIGNvbnN0IG5ld0xpbmVzTWF0Y2hlcyA9IG0ubWF0Y2goX25ld0xpbmVzUmUpO1xuICAgICAgICBjb21tZW50cy5wdXNoKChuZXdMaW5lc01hdGNoZXM/LmpvaW4oJycpID8/ICcnKSArICdcXG4nKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENPTU1FTlRfUExBQ0VIT0xERVI7XG4gICAgfSk7XG5cbiAgICBjc3NUZXh0ID0gdGhpcy5faW5zZXJ0RGlyZWN0aXZlcyhjc3NUZXh0KTtcbiAgICBjb25zdCBzY29wZWRDc3NUZXh0ID0gdGhpcy5fc2NvcGVDc3NUZXh0KGNzc1RleHQsIHNlbGVjdG9yLCBob3N0U2VsZWN0b3IpO1xuICAgIC8vIEFkZCBiYWNrIGNvbW1lbnRzIGF0IHRoZSBvcmlnaW5hbCBwb3NpdGlvbi5cbiAgICBsZXQgY29tbWVudElkeCA9IDA7XG4gICAgcmV0dXJuIHNjb3BlZENzc1RleHQucmVwbGFjZShfY29tbWVudFdpdGhIYXNoUGxhY2VIb2xkZXJSZSwgKCkgPT4gY29tbWVudHNbY29tbWVudElkeCsrXSk7XG4gIH1cblxuICBwcml2YXRlIF9pbnNlcnREaXJlY3RpdmVzKGNzc1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY3NzVGV4dCA9IHRoaXMuX2luc2VydFBvbHlmaWxsRGlyZWN0aXZlc0luQ3NzVGV4dChjc3NUZXh0KTtcbiAgICByZXR1cm4gdGhpcy5faW5zZXJ0UG9seWZpbGxSdWxlc0luQ3NzVGV4dChjc3NUZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzIHN0eWxlcyB0byBhZGQgc2NvcGUgdG8ga2V5ZnJhbWVzLlxuICAgKlxuICAgKiBNb2RpZnkgYm90aCB0aGUgbmFtZXMgb2YgdGhlIGtleWZyYW1lcyBkZWZpbmVkIGluIHRoZSBjb21wb25lbnQgc3R5bGVzIGFuZCBhbHNvIHRoZSBjc3NcbiAgICogYW5pbWF0aW9uIHJ1bGVzIHVzaW5nIHRoZW0uXG4gICAqXG4gICAqIEFuaW1hdGlvbiBydWxlcyB1c2luZyBrZXlmcmFtZXMgZGVmaW5lZCBlbHNld2hlcmUgYXJlIG5vdCBtb2RpZmllZCB0byBhbGxvdyBmb3IgZ2xvYmFsbHlcbiAgICogZGVmaW5lZCBrZXlmcmFtZXMuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB3ZSBjb252ZXJ0IHRoaXMgY3NzOlxuICAgKlxuICAgKiBgYGBcbiAgICogLmJveCB7XG4gICAqICAgYW5pbWF0aW9uOiBib3gtYW5pbWF0aW9uIDFzIGZvcndhcmRzO1xuICAgKiB9XG4gICAqXG4gICAqIEBrZXlmcmFtZXMgYm94LWFuaW1hdGlvbiB7XG4gICAqICAgdG8ge1xuICAgKiAgICAgYmFja2dyb3VuZC1jb2xvcjogZ3JlZW47XG4gICAqICAgfVxuICAgKiB9XG4gICAqIGBgYFxuICAgKlxuICAgKiB0byB0aGlzOlxuICAgKlxuICAgKiBgYGBcbiAgICogLmJveCB7XG4gICAqICAgYW5pbWF0aW9uOiBzY29wZU5hbWVfYm94LWFuaW1hdGlvbiAxcyBmb3J3YXJkcztcbiAgICogfVxuICAgKlxuICAgKiBAa2V5ZnJhbWVzIHNjb3BlTmFtZV9ib3gtYW5pbWF0aW9uIHtcbiAgICogICB0byB7XG4gICAqICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBncmVlbjtcbiAgICogICB9XG4gICAqIH1cbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBjc3NUZXh0IHRoZSBjb21wb25lbnQncyBjc3MgdGV4dCB0aGF0IG5lZWRzIHRvIGJlIHNjb3BlZC5cbiAgICogQHBhcmFtIHNjb3BlU2VsZWN0b3IgdGhlIGNvbXBvbmVudCdzIHNjb3BlIHNlbGVjdG9yLlxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgc2NvcGVkIGNzcyB0ZXh0LlxuICAgKi9cbiAgcHJpdmF0ZSBfc2NvcGVLZXlmcmFtZXNSZWxhdGVkQ3NzKGNzc1RleHQ6IHN0cmluZywgc2NvcGVTZWxlY3Rvcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB1bnNjb3BlZEtleWZyYW1lc1NldCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IHNjb3BlZEtleWZyYW1lc0Nzc1RleHQgPSBwcm9jZXNzUnVsZXMoY3NzVGV4dCwgKHJ1bGUpID0+XG4gICAgICB0aGlzLl9zY29wZUxvY2FsS2V5ZnJhbWVEZWNsYXJhdGlvbnMocnVsZSwgc2NvcGVTZWxlY3RvciwgdW5zY29wZWRLZXlmcmFtZXNTZXQpLFxuICAgICk7XG4gICAgcmV0dXJuIHByb2Nlc3NSdWxlcyhzY29wZWRLZXlmcmFtZXNDc3NUZXh0LCAocnVsZSkgPT5cbiAgICAgIHRoaXMuX3Njb3BlQW5pbWF0aW9uUnVsZShydWxlLCBzY29wZVNlbGVjdG9yLCB1bnNjb3BlZEtleWZyYW1lc1NldCksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY29wZXMgbG9jYWwga2V5ZnJhbWVzIG5hbWVzLCByZXR1cm5pbmcgdGhlIHVwZGF0ZWQgY3NzIHJ1bGUgYW5kIGl0IGFsc29cbiAgICogYWRkcyB0aGUgb3JpZ2luYWwga2V5ZnJhbWUgbmFtZSB0byBhIHByb3ZpZGVkIHNldCB0byBjb2xsZWN0IGFsbCBrZXlmcmFtZXMgbmFtZXNcbiAgICogc28gdGhhdCBpdCBjYW4gbGF0ZXIgYmUgdXNlZCB0byBzY29wZSB0aGUgYW5pbWF0aW9uIHJ1bGVzLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgaXQgdGFrZXMgYSBydWxlIHN1Y2ggYXM6XG4gICAqXG4gICAqIGBgYFxuICAgKiBAa2V5ZnJhbWVzIGJveC1hbmltYXRpb24ge1xuICAgKiAgIHRvIHtcbiAgICogICAgIGJhY2tncm91bmQtY29sb3I6IGdyZWVuO1xuICAgKiAgIH1cbiAgICogfVxuICAgKiBgYGBcbiAgICpcbiAgICogYW5kIHJldHVybnM6XG4gICAqXG4gICAqIGBgYFxuICAgKiBAa2V5ZnJhbWVzIHNjb3BlTmFtZV9ib3gtYW5pbWF0aW9uIHtcbiAgICogICB0byB7XG4gICAqICAgICBiYWNrZ3JvdW5kLWNvbG9yOiBncmVlbjtcbiAgICogICB9XG4gICAqIH1cbiAgICogYGBgXG4gICAqIGFuZCBhcyBhIHNpZGUgZWZmZWN0IGl0IGFkZHMgXCJib3gtYW5pbWF0aW9uXCIgdG8gdGhlIGB1bnNjb3BlZEtleWZyYW1lc1NldGAgc2V0XG4gICAqXG4gICAqIEBwYXJhbSBjc3NSdWxlIHRoZSBjc3MgcnVsZSB0byBwcm9jZXNzLlxuICAgKiBAcGFyYW0gc2NvcGVTZWxlY3RvciB0aGUgY29tcG9uZW50J3Mgc2NvcGUgc2VsZWN0b3IuXG4gICAqIEBwYXJhbSB1bnNjb3BlZEtleWZyYW1lc1NldCB0aGUgc2V0IG9mIHVuc2NvcGVkIGtleWZyYW1lcyBuYW1lcyAod2hpY2ggY2FuIGJlXG4gICAqIG1vZGlmaWVkIGFzIGEgc2lkZSBlZmZlY3QpXG4gICAqXG4gICAqIEByZXR1cm5zIHRoZSBjc3MgcnVsZSBtb2RpZmllZCB3aXRoIHRoZSBzY29wZWQga2V5ZnJhbWVzIG5hbWUuXG4gICAqL1xuICBwcml2YXRlIF9zY29wZUxvY2FsS2V5ZnJhbWVEZWNsYXJhdGlvbnMoXG4gICAgcnVsZTogQ3NzUnVsZSxcbiAgICBzY29wZVNlbGVjdG9yOiBzdHJpbmcsXG4gICAgdW5zY29wZWRLZXlmcmFtZXNTZXQ6IFNldDxzdHJpbmc+LFxuICApOiBDc3NSdWxlIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucnVsZSxcbiAgICAgIHNlbGVjdG9yOiBydWxlLnNlbGVjdG9yLnJlcGxhY2UoXG4gICAgICAgIC8oXkAoPzotd2Via2l0LSk/a2V5ZnJhbWVzKD86XFxzKykpKFsnXCJdPykoLispXFwyKFxccyopJC8sXG4gICAgICAgIChfLCBzdGFydCwgcXVvdGUsIGtleWZyYW1lTmFtZSwgZW5kU3BhY2VzKSA9PiB7XG4gICAgICAgICAgdW5zY29wZWRLZXlmcmFtZXNTZXQuYWRkKHVuZXNjYXBlUXVvdGVzKGtleWZyYW1lTmFtZSwgcXVvdGUpKTtcbiAgICAgICAgICByZXR1cm4gYCR7c3RhcnR9JHtxdW90ZX0ke3Njb3BlU2VsZWN0b3J9XyR7a2V5ZnJhbWVOYW1lfSR7cXVvdGV9JHtlbmRTcGFjZXN9YDtcbiAgICAgICAgfSxcbiAgICAgICksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiB1c2VkIHRvIHNjb3BlIGEga2V5ZnJhbWVzIG5hbWUgKG9idGFpbmVkIGZyb20gYW4gYW5pbWF0aW9uIGRlY2xhcmF0aW9uKVxuICAgKiB1c2luZyBhbiBleGlzdGluZyBzZXQgb2YgdW5zY29wZWRLZXlmcmFtZXMgbmFtZXMgdG8gZGlzY2VybiBpZiB0aGUgc2NvcGluZyBuZWVkcyB0byBiZVxuICAgKiBwZXJmb3JtZWQgKGtleWZyYW1lcyBuYW1lcyBvZiBrZXlmcmFtZXMgbm90IGRlZmluZWQgaW4gdGhlIGNvbXBvbmVudCdzIGNzcyBuZWVkIG5vdCB0byBiZVxuICAgKiBzY29wZWQpLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5ZnJhbWUgdGhlIGtleWZyYW1lcyBuYW1lIHRvIGNoZWNrLlxuICAgKiBAcGFyYW0gc2NvcGVTZWxlY3RvciB0aGUgY29tcG9uZW50J3Mgc2NvcGUgc2VsZWN0b3IuXG4gICAqIEBwYXJhbSB1bnNjb3BlZEtleWZyYW1lc1NldCB0aGUgc2V0IG9mIHVuc2NvcGVkIGtleWZyYW1lcyBuYW1lcy5cbiAgICpcbiAgICogQHJldHVybnMgdGhlIHNjb3BlZCBuYW1lIG9mIHRoZSBrZXlmcmFtZSwgb3IgdGhlIG9yaWdpbmFsIG5hbWUgaXMgdGhlIG5hbWUgbmVlZCBub3QgdG8gYmVcbiAgICogc2NvcGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfc2NvcGVBbmltYXRpb25LZXlmcmFtZShcbiAgICBrZXlmcmFtZTogc3RyaW5nLFxuICAgIHNjb3BlU2VsZWN0b3I6IHN0cmluZyxcbiAgICB1bnNjb3BlZEtleWZyYW1lc1NldDogUmVhZG9ubHlTZXQ8c3RyaW5nPixcbiAgKTogc3RyaW5nIHtcbiAgICByZXR1cm4ga2V5ZnJhbWUucmVwbGFjZSgvXihcXHMqKShbJ1wiXT8pKC4rPylcXDIoXFxzKikkLywgKF8sIHNwYWNlczEsIHF1b3RlLCBuYW1lLCBzcGFjZXMyKSA9PiB7XG4gICAgICBuYW1lID0gYCR7dW5zY29wZWRLZXlmcmFtZXNTZXQuaGFzKHVuZXNjYXBlUXVvdGVzKG5hbWUsIHF1b3RlKSkgPyBzY29wZVNlbGVjdG9yICsgJ18nIDogJyd9JHtuYW1lfWA7XG4gICAgICByZXR1cm4gYCR7c3BhY2VzMX0ke3F1b3RlfSR7bmFtZX0ke3F1b3RlfSR7c3BhY2VzMn1gO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ3VsYXIgZXhwcmVzc2lvbiB1c2VkIHRvIGV4dHJhcG9sYXRlIHRoZSBwb3NzaWJsZSBrZXlmcmFtZXMgZnJvbSBhblxuICAgKiBhbmltYXRpb24gZGVjbGFyYXRpb24gKHdpdGggcG9zc2libHkgbXVsdGlwbGUgYW5pbWF0aW9uIGRlZmluaXRpb25zKVxuICAgKlxuICAgKiBUaGUgcmVndWxhciBleHByZXNzaW9uIGNhbiBiZSBkaXZpZGVkIGluIHRocmVlIHBhcnRzXG4gICAqICAtIChefFxccyt8LClcbiAgICogICAgY2FwdHVyZXMgaG93IG1hbnkgKGlmIGFueSkgbGVhZGluZyB3aGl0ZXNwYWNlcyBhcmUgcHJlc2VudCBvciBhIGNvbW1hXG4gICAqICAtICg/Oig/OihbJ1wiXSkoKD86XFxcXFxcXFx8XFxcXFxcMnwoPyFcXDIpLikrKVxcMil8KC0/W0EtWmEtel1bXFx3XFwtXSopKVxuICAgKiAgICBjYXB0dXJlcyB0d28gZGlmZmVyZW50IHBvc3NpYmxlIGtleWZyYW1lcywgb25lcyB3aGljaCBhcmUgcXVvdGVkIG9yIG9uZXMgd2hpY2ggYXJlIHZhbGlkIGNzc1xuICAgKiBpZGVudHMgKGN1c3RvbSBwcm9wZXJ0aWVzIGV4Y2x1ZGVkKVxuICAgKiAgLSAoPz1bLFxccztdfCQpXG4gICAqICAgIHNpbXBseSBtYXRjaGVzIHRoZSBlbmQgb2YgdGhlIHBvc3NpYmxlIGtleWZyYW1lLCB2YWxpZCBlbmRpbmdzIGFyZTogYSBjb21tYSwgYSBzcGFjZSwgYVxuICAgKiBzZW1pY29sb24gb3IgdGhlIGVuZCBvZiB0aGUgc3RyaW5nXG4gICAqL1xuICBwcml2YXRlIF9hbmltYXRpb25EZWNsYXJhdGlvbktleWZyYW1lc1JlID1cbiAgICAvKF58XFxzK3wsKSg/Oig/OihbJ1wiXSkoKD86XFxcXFxcXFx8XFxcXFxcMnwoPyFcXDIpLikrKVxcMil8KC0/W0EtWmEtel1bXFx3XFwtXSopKSg/PVssXFxzXXwkKS9nO1xuXG4gIC8qKlxuICAgKiBTY29wZSBhbiBhbmltYXRpb24gcnVsZSBzbyB0aGF0IHRoZSBrZXlmcmFtZXMgbWVudGlvbmVkIGluIHN1Y2ggcnVsZVxuICAgKiBhcmUgc2NvcGVkIGlmIGRlZmluZWQgaW4gdGhlIGNvbXBvbmVudCdzIGNzcyBhbmQgbGVmdCB1bnRvdWNoZWQgb3RoZXJ3aXNlLlxuICAgKlxuICAgKiBJdCBjYW4gc2NvcGUgdmFsdWVzIG9mIGJvdGggdGhlICdhbmltYXRpb24nIGFuZCAnYW5pbWF0aW9uLW5hbWUnIHByb3BlcnRpZXMuXG4gICAqXG4gICAqIEBwYXJhbSBydWxlIGNzcyBydWxlIHRvIHNjb3BlLlxuICAgKiBAcGFyYW0gc2NvcGVTZWxlY3RvciB0aGUgY29tcG9uZW50J3Mgc2NvcGUgc2VsZWN0b3IuXG4gICAqIEBwYXJhbSB1bnNjb3BlZEtleWZyYW1lc1NldCB0aGUgc2V0IG9mIHVuc2NvcGVkIGtleWZyYW1lcyBuYW1lcy5cbiAgICpcbiAgICogQHJldHVybnMgdGhlIHVwZGF0ZWQgY3NzIHJ1bGUuXG4gICAqKi9cbiAgcHJpdmF0ZSBfc2NvcGVBbmltYXRpb25SdWxlKFxuICAgIHJ1bGU6IENzc1J1bGUsXG4gICAgc2NvcGVTZWxlY3Rvcjogc3RyaW5nLFxuICAgIHVuc2NvcGVkS2V5ZnJhbWVzU2V0OiBSZWFkb25seVNldDxzdHJpbmc+LFxuICApOiBDc3NSdWxlIHtcbiAgICBsZXQgY29udGVudCA9IHJ1bGUuY29udGVudC5yZXBsYWNlKFxuICAgICAgLygoPzpefFxccyt8OykoPzotd2Via2l0LSk/YW5pbWF0aW9uXFxzKjpcXHMqKSwqKFteO10rKS9nLFxuICAgICAgKF8sIHN0YXJ0LCBhbmltYXRpb25EZWNsYXJhdGlvbnMpID0+XG4gICAgICAgIHN0YXJ0ICtcbiAgICAgICAgYW5pbWF0aW9uRGVjbGFyYXRpb25zLnJlcGxhY2UoXG4gICAgICAgICAgdGhpcy5fYW5pbWF0aW9uRGVjbGFyYXRpb25LZXlmcmFtZXNSZSxcbiAgICAgICAgICAoXG4gICAgICAgICAgICBvcmlnaW5hbDogc3RyaW5nLFxuICAgICAgICAgICAgbGVhZGluZ1NwYWNlczogc3RyaW5nLFxuICAgICAgICAgICAgcXVvdGUgPSAnJyxcbiAgICAgICAgICAgIHF1b3RlZE5hbWU6IHN0cmluZyxcbiAgICAgICAgICAgIG5vblF1b3RlZE5hbWU6IHN0cmluZyxcbiAgICAgICAgICApID0+IHtcbiAgICAgICAgICAgIGlmIChxdW90ZWROYW1lKSB7XG4gICAgICAgICAgICAgIHJldHVybiBgJHtsZWFkaW5nU3BhY2VzfSR7dGhpcy5fc2NvcGVBbmltYXRpb25LZXlmcmFtZShcbiAgICAgICAgICAgICAgICBgJHtxdW90ZX0ke3F1b3RlZE5hbWV9JHtxdW90ZX1gLFxuICAgICAgICAgICAgICAgIHNjb3BlU2VsZWN0b3IsXG4gICAgICAgICAgICAgICAgdW5zY29wZWRLZXlmcmFtZXNTZXQsXG4gICAgICAgICAgICAgICl9YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBhbmltYXRpb25LZXl3b3Jkcy5oYXMobm9uUXVvdGVkTmFtZSlcbiAgICAgICAgICAgICAgICA/IG9yaWdpbmFsXG4gICAgICAgICAgICAgICAgOiBgJHtsZWFkaW5nU3BhY2VzfSR7dGhpcy5fc2NvcGVBbmltYXRpb25LZXlmcmFtZShcbiAgICAgICAgICAgICAgICAgICAgbm9uUXVvdGVkTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgc2NvcGVTZWxlY3RvcixcbiAgICAgICAgICAgICAgICAgICAgdW5zY29wZWRLZXlmcmFtZXNTZXQsXG4gICAgICAgICAgICAgICAgICApfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICApO1xuICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoXG4gICAgICAvKCg/Ol58XFxzK3w7KSg/Oi13ZWJraXQtKT9hbmltYXRpb24tbmFtZSg/OlxccyopOig/OlxccyopKShbXjtdKykvZyxcbiAgICAgIChfbWF0Y2gsIHN0YXJ0LCBjb21tYVNlcGFyYXRlZEtleWZyYW1lcykgPT5cbiAgICAgICAgYCR7c3RhcnR9JHtjb21tYVNlcGFyYXRlZEtleWZyYW1lc1xuICAgICAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAgICAgLm1hcCgoa2V5ZnJhbWU6IHN0cmluZykgPT5cbiAgICAgICAgICAgIHRoaXMuX3Njb3BlQW5pbWF0aW9uS2V5ZnJhbWUoa2V5ZnJhbWUsIHNjb3BlU2VsZWN0b3IsIHVuc2NvcGVkS2V5ZnJhbWVzU2V0KSxcbiAgICAgICAgICApXG4gICAgICAgICAgLmpvaW4oJywnKX1gLFxuICAgICk7XG4gICAgcmV0dXJuIHsuLi5ydWxlLCBjb250ZW50fTtcbiAgfVxuXG4gIC8qXG4gICAqIFByb2Nlc3Mgc3R5bGVzIHRvIGNvbnZlcnQgbmF0aXZlIFNoYWRvd0RPTSBydWxlcyB0aGF0IHdpbGwgdHJpcFxuICAgKiB1cCB0aGUgY3NzIHBhcnNlcjsgd2UgcmVseSBvbiBkZWNvcmF0aW5nIHRoZSBzdHlsZXNoZWV0IHdpdGggaW5lcnQgcnVsZXMuXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB3ZSBjb252ZXJ0IHRoaXMgcnVsZTpcbiAgICpcbiAgICogcG9seWZpbGwtbmV4dC1zZWxlY3RvciB7IGNvbnRlbnQ6ICc6aG9zdCBtZW51LWl0ZW0nOyB9XG4gICAqIDo6Y29udGVudCBtZW51LWl0ZW0ge1xuICAgKlxuICAgKiB0byB0aGlzOlxuICAgKlxuICAgKiBzY29wZU5hbWUgbWVudS1pdGVtIHtcbiAgICpcbiAgICoqL1xuICBwcml2YXRlIF9pbnNlcnRQb2x5ZmlsbERpcmVjdGl2ZXNJbkNzc1RleHQoY3NzVGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY3NzVGV4dC5yZXBsYWNlKF9jc3NDb250ZW50TmV4dFNlbGVjdG9yUmUsIGZ1bmN0aW9uICguLi5tOiBzdHJpbmdbXSkge1xuICAgICAgcmV0dXJuIG1bMl0gKyAneyc7XG4gICAgfSk7XG4gIH1cblxuICAvKlxuICAgKiBQcm9jZXNzIHN0eWxlcyB0byBhZGQgcnVsZXMgd2hpY2ggd2lsbCBvbmx5IGFwcGx5IHVuZGVyIHRoZSBwb2x5ZmlsbFxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgd2UgY29udmVydCB0aGlzIHJ1bGU6XG4gICAqXG4gICAqIHBvbHlmaWxsLXJ1bGUge1xuICAgKiAgIGNvbnRlbnQ6ICc6aG9zdCBtZW51LWl0ZW0nO1xuICAgKiAuLi5cbiAgICogfVxuICAgKlxuICAgKiB0byB0aGlzOlxuICAgKlxuICAgKiBzY29wZU5hbWUgbWVudS1pdGVtIHsuLi59XG4gICAqXG4gICAqKi9cbiAgcHJpdmF0ZSBfaW5zZXJ0UG9seWZpbGxSdWxlc0luQ3NzVGV4dChjc3NUZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjc3NUZXh0LnJlcGxhY2UoX2Nzc0NvbnRlbnRSdWxlUmUsICguLi5tOiBzdHJpbmdbXSkgPT4ge1xuICAgICAgY29uc3QgcnVsZSA9IG1bMF0ucmVwbGFjZShtWzFdLCAnJykucmVwbGFjZShtWzJdLCAnJyk7XG4gICAgICByZXR1cm4gbVs0XSArIHJ1bGU7XG4gICAgfSk7XG4gIH1cblxuICAvKiBFbnN1cmUgc3R5bGVzIGFyZSBzY29wZWQuIFBzZXVkby1zY29waW5nIHRha2VzIGEgcnVsZSBsaWtlOlxuICAgKlxuICAgKiAgLmZvbyB7Li4uIH1cbiAgICpcbiAgICogIGFuZCBjb252ZXJ0cyB0aGlzIHRvXG4gICAqXG4gICAqICBzY29wZU5hbWUgLmZvbyB7IC4uLiB9XG4gICAqL1xuICBwcml2YXRlIF9zY29wZUNzc1RleHQoY3NzVGV4dDogc3RyaW5nLCBzY29wZVNlbGVjdG9yOiBzdHJpbmcsIGhvc3RTZWxlY3Rvcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB1bnNjb3BlZFJ1bGVzID0gdGhpcy5fZXh0cmFjdFVuc2NvcGVkUnVsZXNGcm9tQ3NzVGV4dChjc3NUZXh0KTtcbiAgICAvLyByZXBsYWNlIDpob3N0IGFuZCA6aG9zdC1jb250ZXh0IC1zaGFkb3djc3Nob3N0IGFuZCAtc2hhZG93Y3NzaG9zdCByZXNwZWN0aXZlbHlcbiAgICBjc3NUZXh0ID0gdGhpcy5faW5zZXJ0UG9seWZpbGxIb3N0SW5Dc3NUZXh0KGNzc1RleHQpO1xuICAgIGNzc1RleHQgPSB0aGlzLl9jb252ZXJ0Q29sb25Ib3N0KGNzc1RleHQpO1xuICAgIGNzc1RleHQgPSB0aGlzLl9jb252ZXJ0Q29sb25Ib3N0Q29udGV4dChjc3NUZXh0KTtcbiAgICBjc3NUZXh0ID0gdGhpcy5fY29udmVydFNoYWRvd0RPTVNlbGVjdG9ycyhjc3NUZXh0KTtcbiAgICBpZiAoc2NvcGVTZWxlY3Rvcikge1xuICAgICAgY3NzVGV4dCA9IHRoaXMuX3Njb3BlS2V5ZnJhbWVzUmVsYXRlZENzcyhjc3NUZXh0LCBzY29wZVNlbGVjdG9yKTtcbiAgICAgIGNzc1RleHQgPSB0aGlzLl9zY29wZVNlbGVjdG9ycyhjc3NUZXh0LCBzY29wZVNlbGVjdG9yLCBob3N0U2VsZWN0b3IpO1xuICAgIH1cbiAgICBjc3NUZXh0ID0gY3NzVGV4dCArICdcXG4nICsgdW5zY29wZWRSdWxlcztcbiAgICByZXR1cm4gY3NzVGV4dC50cmltKCk7XG4gIH1cblxuICAvKlxuICAgKiBQcm9jZXNzIHN0eWxlcyB0byBhZGQgcnVsZXMgd2hpY2ggd2lsbCBvbmx5IGFwcGx5IHVuZGVyIHRoZSBwb2x5ZmlsbFxuICAgKiBhbmQgZG8gbm90IHByb2Nlc3MgdmlhIENTU09NLiAoQ1NTT00gaXMgZGVzdHJ1Y3RpdmUgdG8gcnVsZXMgb24gcmFyZVxuICAgKiBvY2Nhc2lvbnMsIGUuZy4gLXdlYmtpdC1jYWxjIG9uIFNhZmFyaS4pXG4gICAqIEZvciBleGFtcGxlLCB3ZSBjb252ZXJ0IHRoaXMgcnVsZTpcbiAgICpcbiAgICogQHBvbHlmaWxsLXVuc2NvcGVkLXJ1bGUge1xuICAgKiAgIGNvbnRlbnQ6ICdtZW51LWl0ZW0nO1xuICAgKiAuLi4gfVxuICAgKlxuICAgKiB0byB0aGlzOlxuICAgKlxuICAgKiBtZW51LWl0ZW0gey4uLn1cbiAgICpcbiAgICoqL1xuICBwcml2YXRlIF9leHRyYWN0VW5zY29wZWRSdWxlc0Zyb21Dc3NUZXh0KGNzc1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IHIgPSAnJztcbiAgICBsZXQgbTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbDtcbiAgICBfY3NzQ29udGVudFVuc2NvcGVkUnVsZVJlLmxhc3RJbmRleCA9IDA7XG4gICAgd2hpbGUgKChtID0gX2Nzc0NvbnRlbnRVbnNjb3BlZFJ1bGVSZS5leGVjKGNzc1RleHQpKSAhPT0gbnVsbCkge1xuICAgICAgY29uc3QgcnVsZSA9IG1bMF0ucmVwbGFjZShtWzJdLCAnJykucmVwbGFjZShtWzFdLCBtWzRdKTtcbiAgICAgIHIgKz0gcnVsZSArICdcXG5cXG4nO1xuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfVxuXG4gIC8qXG4gICAqIGNvbnZlcnQgYSBydWxlIGxpa2UgOmhvc3QoLmZvbykgPiAuYmFyIHsgfVxuICAgKlxuICAgKiB0b1xuICAgKlxuICAgKiAuZm9vPHNjb3BlTmFtZT4gPiAuYmFyXG4gICAqL1xuICBwcml2YXRlIF9jb252ZXJ0Q29sb25Ib3N0KGNzc1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNzc1RleHQucmVwbGFjZShfY3NzQ29sb25Ib3N0UmUsIChfLCBob3N0U2VsZWN0b3JzOiBzdHJpbmcsIG90aGVyU2VsZWN0b3JzOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmIChob3N0U2VsZWN0b3JzKSB7XG4gICAgICAgIGNvbnN0IGNvbnZlcnRlZFNlbGVjdG9yczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgaG9zdFNlbGVjdG9yQXJyYXkgPSBob3N0U2VsZWN0b3JzLnNwbGl0KCcsJykubWFwKChwKSA9PiBwLnRyaW0oKSk7XG4gICAgICAgIGZvciAoY29uc3QgaG9zdFNlbGVjdG9yIG9mIGhvc3RTZWxlY3RvckFycmF5KSB7XG4gICAgICAgICAgaWYgKCFob3N0U2VsZWN0b3IpIGJyZWFrO1xuICAgICAgICAgIGNvbnN0IGNvbnZlcnRlZFNlbGVjdG9yID1cbiAgICAgICAgICAgIF9wb2x5ZmlsbEhvc3ROb0NvbWJpbmF0b3IgKyBob3N0U2VsZWN0b3IucmVwbGFjZShfcG9seWZpbGxIb3N0LCAnJykgKyBvdGhlclNlbGVjdG9ycztcbiAgICAgICAgICBjb252ZXJ0ZWRTZWxlY3RvcnMucHVzaChjb252ZXJ0ZWRTZWxlY3Rvcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFNlbGVjdG9ycy5qb2luKCcsJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvciArIG90aGVyU2VsZWN0b3JzO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLypcbiAgICogY29udmVydCBhIHJ1bGUgbGlrZSA6aG9zdC1jb250ZXh0KC5mb28pID4gLmJhciB7IH1cbiAgICpcbiAgICogdG9cbiAgICpcbiAgICogLmZvbzxzY29wZU5hbWU+ID4gLmJhciwgLmZvbyA8c2NvcGVOYW1lPiA+IC5iYXIgeyB9XG4gICAqXG4gICAqIGFuZFxuICAgKlxuICAgKiA6aG9zdC1jb250ZXh0KC5mb286aG9zdCkgLmJhciB7IC4uLiB9XG4gICAqXG4gICAqIHRvXG4gICAqXG4gICAqIC5mb288c2NvcGVOYW1lPiAuYmFyIHsgLi4uIH1cbiAgICovXG4gIHByaXZhdGUgX2NvbnZlcnRDb2xvbkhvc3RDb250ZXh0KGNzc1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNzc1RleHQucmVwbGFjZShfY3NzQ29sb25Ib3N0Q29udGV4dFJlR2xvYmFsLCAoc2VsZWN0b3JUZXh0KSA9PiB7XG4gICAgICAvLyBXZSBoYXZlIGNhcHR1cmVkIGEgc2VsZWN0b3IgdGhhdCBjb250YWlucyBhIGA6aG9zdC1jb250ZXh0YCBydWxlLlxuXG4gICAgICAvLyBGb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBgOmhvc3QtY29udGV4dGAgbWF5IGNvbnRhaW4gYSBjb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiBzZWxlY3RvcnMuXG4gICAgICAvLyBFYWNoIGNvbnRleHQgc2VsZWN0b3IgZ3JvdXAgd2lsbCBjb250YWluIGEgbGlzdCBvZiBob3N0LWNvbnRleHQgc2VsZWN0b3JzIHRoYXQgbXVzdCBtYXRjaFxuICAgICAgLy8gYW4gYW5jZXN0b3Igb2YgdGhlIGhvc3QuXG4gICAgICAvLyAoTm9ybWFsbHkgYGNvbnRleHRTZWxlY3Rvckdyb3Vwc2Agd2lsbCBvbmx5IGNvbnRhaW4gYSBzaW5nbGUgYXJyYXkgb2YgY29udGV4dCBzZWxlY3RvcnMuKVxuICAgICAgY29uc3QgY29udGV4dFNlbGVjdG9yR3JvdXBzOiBzdHJpbmdbXVtdID0gW1tdXTtcblxuICAgICAgLy8gVGhlcmUgbWF5IGJlIG1vcmUgdGhhbiBgOmhvc3QtY29udGV4dGAgaW4gdGhpcyBzZWxlY3RvciBzbyBgc2VsZWN0b3JUZXh0YCBjb3VsZCBsb29rIGxpa2U6XG4gICAgICAvLyBgOmhvc3QtY29udGV4dCgub25lKTpob3N0LWNvbnRleHQoLnR3bylgLlxuICAgICAgLy8gRXhlY3V0ZSBgX2Nzc0NvbG9uSG9zdENvbnRleHRSZWAgb3ZlciBhbmQgb3ZlciB1bnRpbCB3ZSBoYXZlIGV4dHJhY3RlZCBhbGwgdGhlXG4gICAgICAvLyBgOmhvc3QtY29udGV4dGAgc2VsZWN0b3JzIGZyb20gdGhpcyBzZWxlY3Rvci5cbiAgICAgIGxldCBtYXRjaDogUmVnRXhwRXhlY0FycmF5IHwgbnVsbDtcbiAgICAgIHdoaWxlICgobWF0Y2ggPSBfY3NzQ29sb25Ib3N0Q29udGV4dFJlLmV4ZWMoc2VsZWN0b3JUZXh0KSkpIHtcbiAgICAgICAgLy8gYG1hdGNoYCA9IFsnOmhvc3QtY29udGV4dCg8c2VsZWN0b3JzPik8cmVzdD4nLCA8c2VsZWN0b3JzPiwgPHJlc3Q+XVxuXG4gICAgICAgIC8vIFRoZSBgPHNlbGVjdG9ycz5gIGNvdWxkIGFjdHVhbGx5IGJlIGEgY29tbWEgc2VwYXJhdGVkIGxpc3Q6IGA6aG9zdC1jb250ZXh0KC5vbmUsIC50d28pYC5cbiAgICAgICAgY29uc3QgbmV3Q29udGV4dFNlbGVjdG9ycyA9IChtYXRjaFsxXSA/PyAnJylcbiAgICAgICAgICAudHJpbSgpXG4gICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAubWFwKChtKSA9PiBtLnRyaW0oKSlcbiAgICAgICAgICAuZmlsdGVyKChtKSA9PiBtICE9PSAnJyk7XG5cbiAgICAgICAgLy8gV2UgbXVzdCBkdXBsaWNhdGUgdGhlIGN1cnJlbnQgc2VsZWN0b3IgZ3JvdXAgZm9yIGVhY2ggb2YgdGhlc2UgbmV3IHNlbGVjdG9ycy5cbiAgICAgICAgLy8gRm9yIGV4YW1wbGUgaWYgdGhlIGN1cnJlbnQgZ3JvdXBzIGFyZTpcbiAgICAgICAgLy8gYGBgXG4gICAgICAgIC8vIFtcbiAgICAgICAgLy8gICBbJ2EnLCAnYicsICdjJ10sXG4gICAgICAgIC8vICAgWyd4JywgJ3knLCAneiddLFxuICAgICAgICAvLyBdXG4gICAgICAgIC8vIGBgYFxuICAgICAgICAvLyBBbmQgd2UgaGF2ZSBhIG5ldyBzZXQgb2YgY29tbWEgc2VwYXJhdGVkIHNlbGVjdG9yczogYDpob3N0LWNvbnRleHQobSxuKWAgdGhlbiB0aGUgbmV3XG4gICAgICAgIC8vIGdyb3VwcyBhcmU6XG4gICAgICAgIC8vIGBgYFxuICAgICAgICAvLyBbXG4gICAgICAgIC8vICAgWydhJywgJ2InLCAnYycsICdtJ10sXG4gICAgICAgIC8vICAgWyd4JywgJ3knLCAneicsICdtJ10sXG4gICAgICAgIC8vICAgWydhJywgJ2InLCAnYycsICduJ10sXG4gICAgICAgIC8vICAgWyd4JywgJ3knLCAneicsICduJ10sXG4gICAgICAgIC8vIF1cbiAgICAgICAgLy8gYGBgXG4gICAgICAgIGNvbnN0IGNvbnRleHRTZWxlY3Rvckdyb3Vwc0xlbmd0aCA9IGNvbnRleHRTZWxlY3Rvckdyb3Vwcy5sZW5ndGg7XG4gICAgICAgIHJlcGVhdEdyb3Vwcyhjb250ZXh0U2VsZWN0b3JHcm91cHMsIG5ld0NvbnRleHRTZWxlY3RvcnMubGVuZ3RoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdDb250ZXh0U2VsZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjb250ZXh0U2VsZWN0b3JHcm91cHNMZW5ndGg7IGorKykge1xuICAgICAgICAgICAgY29udGV4dFNlbGVjdG9yR3JvdXBzW2ogKyBpICogY29udGV4dFNlbGVjdG9yR3JvdXBzTGVuZ3RoXS5wdXNoKG5ld0NvbnRleHRTZWxlY3RvcnNbaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgYHNlbGVjdG9yVGV4dGAgYW5kIHNlZSByZXBlYXQgdG8gc2VlIGlmIHRoZXJlIGFyZSBtb3JlIGA6aG9zdC1jb250ZXh0YHMuXG4gICAgICAgIHNlbGVjdG9yVGV4dCA9IG1hdGNoWzJdO1xuICAgICAgfVxuXG4gICAgICAvLyBUaGUgY29udGV4dCBzZWxlY3RvcnMgbm93IG11c3QgYmUgY29tYmluZWQgd2l0aCBlYWNoIG90aGVyIHRvIGNhcHR1cmUgYWxsIHRoZSBwb3NzaWJsZVxuICAgICAgLy8gc2VsZWN0b3JzIHRoYXQgYDpob3N0LWNvbnRleHRgIGNhbiBtYXRjaC4gU2VlIGBjb21iaW5lSG9zdENvbnRleHRTZWxlY3RvcnMoKWAgZm9yIG1vcmVcbiAgICAgIC8vIGluZm8gYWJvdXQgaG93IHRoaXMgaXMgZG9uZS5cbiAgICAgIHJldHVybiBjb250ZXh0U2VsZWN0b3JHcm91cHNcbiAgICAgICAgLm1hcCgoY29udGV4dFNlbGVjdG9ycykgPT4gY29tYmluZUhvc3RDb250ZXh0U2VsZWN0b3JzKGNvbnRleHRTZWxlY3RvcnMsIHNlbGVjdG9yVGV4dCkpXG4gICAgICAgIC5qb2luKCcsICcpO1xuICAgIH0pO1xuICB9XG5cbiAgLypcbiAgICogQ29udmVydCBjb21iaW5hdG9ycyBsaWtlIDo6c2hhZG93IGFuZCBwc2V1ZG8tZWxlbWVudHMgbGlrZSA6OmNvbnRlbnRcbiAgICogYnkgcmVwbGFjaW5nIHdpdGggc3BhY2UuXG4gICAqL1xuICBwcml2YXRlIF9jb252ZXJ0U2hhZG93RE9NU2VsZWN0b3JzKGNzc1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIF9zaGFkb3dET01TZWxlY3RvcnNSZS5yZWR1Y2UoKHJlc3VsdCwgcGF0dGVybikgPT4gcmVzdWx0LnJlcGxhY2UocGF0dGVybiwgJyAnKSwgY3NzVGV4dCk7XG4gIH1cblxuICAvLyBjaGFuZ2UgYSBzZWxlY3RvciBsaWtlICdkaXYnIHRvICduYW1lIGRpdidcbiAgcHJpdmF0ZSBfc2NvcGVTZWxlY3RvcnMoY3NzVGV4dDogc3RyaW5nLCBzY29wZVNlbGVjdG9yOiBzdHJpbmcsIGhvc3RTZWxlY3Rvcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcHJvY2Vzc1J1bGVzKGNzc1RleHQsIChydWxlOiBDc3NSdWxlKSA9PiB7XG4gICAgICBsZXQgc2VsZWN0b3IgPSBydWxlLnNlbGVjdG9yO1xuICAgICAgbGV0IGNvbnRlbnQgPSBydWxlLmNvbnRlbnQ7XG4gICAgICBpZiAocnVsZS5zZWxlY3RvclswXSAhPT0gJ0AnKSB7XG4gICAgICAgIHNlbGVjdG9yID0gdGhpcy5fc2NvcGVTZWxlY3RvcihydWxlLnNlbGVjdG9yLCBzY29wZVNlbGVjdG9yLCBob3N0U2VsZWN0b3IpO1xuICAgICAgfSBlbHNlIGlmIChzY29wZWRBdFJ1bGVJZGVudGlmaWVycy5zb21lKChhdFJ1bGUpID0+IHJ1bGUuc2VsZWN0b3Iuc3RhcnRzV2l0aChhdFJ1bGUpKSkge1xuICAgICAgICBjb250ZW50ID0gdGhpcy5fc2NvcGVTZWxlY3RvcnMocnVsZS5jb250ZW50LCBzY29wZVNlbGVjdG9yLCBob3N0U2VsZWN0b3IpO1xuICAgICAgfSBlbHNlIGlmIChydWxlLnNlbGVjdG9yLnN0YXJ0c1dpdGgoJ0Bmb250LWZhY2UnKSB8fCBydWxlLnNlbGVjdG9yLnN0YXJ0c1dpdGgoJ0BwYWdlJykpIHtcbiAgICAgICAgY29udGVudCA9IHRoaXMuX3N0cmlwU2NvcGluZ1NlbGVjdG9ycyhydWxlLmNvbnRlbnQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBDc3NSdWxlKHNlbGVjdG9yLCBjb250ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgYSBjc3MgdGV4dCB0aGF0IGlzIHdpdGhpbiBhIHJ1bGUgdGhhdCBzaG91bGQgbm90IGNvbnRhaW4gc2NvcGUgc2VsZWN0b3JzIGJ5IHNpbXBseVxuICAgKiByZW1vdmluZyB0aGVtISBBbiBleGFtcGxlIG9mIHN1Y2ggYSBydWxlIGlzIGBAZm9udC1mYWNlYC5cbiAgICpcbiAgICogYEBmb250LWZhY2VgIHJ1bGVzIGNhbm5vdCBjb250YWluIG5lc3RlZCBzZWxlY3RvcnMuIE5vciBjYW4gdGhleSBiZSBuZXN0ZWQgdW5kZXIgYSBzZWxlY3Rvci5cbiAgICogTm9ybWFsbHkgdGhpcyB3b3VsZCBiZSBhIHN5bnRheCBlcnJvciBieSB0aGUgYXV0aG9yIG9mIHRoZSBzdHlsZXMuIEJ1dCBpbiBzb21lIHJhcmUgY2FzZXMsIHN1Y2hcbiAgICogYXMgaW1wb3J0aW5nIHN0eWxlcyBmcm9tIGEgbGlicmFyeSwgYW5kIGFwcGx5aW5nIGA6aG9zdCA6Om5nLWRlZXBgIHRvIHRoZSBpbXBvcnRlZCBzdHlsZXMsIHdlXG4gICAqIGNhbiBlbmQgdXAgd2l0aCBicm9rZW4gY3NzIGlmIHRoZSBpbXBvcnRlZCBzdHlsZXMgaGFwcGVuIHRvIGNvbnRhaW4gQGZvbnQtZmFjZSBydWxlcy5cbiAgICpcbiAgICogRm9yIGV4YW1wbGU6XG4gICAqXG4gICAqIGBgYFxuICAgKiA6aG9zdCA6Om5nLWRlZXAge1xuICAgKiAgIGltcG9ydCAnc29tZS9saWIvY29udGFpbmluZy9mb250LWZhY2UnO1xuICAgKiB9XG4gICAqXG4gICAqIFNpbWlsYXIgbG9naWMgYXBwbGllcyB0byBgQHBhZ2VgIHJ1bGVzIHdoaWNoIGNhbiBjb250YWluIGEgcGFydGljdWxhciBzZXQgb2YgcHJvcGVydGllcyxcbiAgICogYXMgd2VsbCBhcyBzb21lIHNwZWNpZmljIGF0LXJ1bGVzLiBTaW5jZSB0aGV5IGNhbid0IGJlIGVuY2Fwc3VsYXRlZCwgd2UgaGF2ZSB0byBzdHJpcFxuICAgKiBhbnkgc2NvcGluZyBzZWxlY3RvcnMgZnJvbSB0aGVtLiBGb3IgbW9yZSBpbmZvcm1hdGlvbjogaHR0cHM6Ly93d3cudzMub3JnL1RSL2Nzcy1wYWdlLTNcbiAgICogYGBgXG4gICAqL1xuICBwcml2YXRlIF9zdHJpcFNjb3BpbmdTZWxlY3RvcnMoY3NzVGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcHJvY2Vzc1J1bGVzKGNzc1RleHQsIChydWxlKSA9PiB7XG4gICAgICBjb25zdCBzZWxlY3RvciA9IHJ1bGUuc2VsZWN0b3JcbiAgICAgICAgLnJlcGxhY2UoX3NoYWRvd0RlZXBTZWxlY3RvcnMsICcgJylcbiAgICAgICAgLnJlcGxhY2UoX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvclJlLCAnICcpO1xuICAgICAgcmV0dXJuIG5ldyBDc3NSdWxlKHNlbGVjdG9yLCBydWxlLmNvbnRlbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2NvcGVTZWxlY3RvcihzZWxlY3Rvcjogc3RyaW5nLCBzY29wZVNlbGVjdG9yOiBzdHJpbmcsIGhvc3RTZWxlY3Rvcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gc2VsZWN0b3JcbiAgICAgIC5zcGxpdCgvID8sID8vKVxuICAgICAgLm1hcCgocGFydCkgPT4gcGFydC5zcGxpdChfc2hhZG93RGVlcFNlbGVjdG9ycykpXG4gICAgICAubWFwKChkZWVwUGFydHMpID0+IHtcbiAgICAgICAgY29uc3QgW3NoYWxsb3dQYXJ0LCAuLi5vdGhlclBhcnRzXSA9IGRlZXBQYXJ0cztcbiAgICAgICAgY29uc3QgYXBwbHlTY29wZSA9IChzaGFsbG93UGFydDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX3NlbGVjdG9yTmVlZHNTY29waW5nKHNoYWxsb3dQYXJ0LCBzY29wZVNlbGVjdG9yKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5U2VsZWN0b3JTY29wZShzaGFsbG93UGFydCwgc2NvcGVTZWxlY3RvciwgaG9zdFNlbGVjdG9yKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHNoYWxsb3dQYXJ0O1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFthcHBseVNjb3BlKHNoYWxsb3dQYXJ0KSwgLi4ub3RoZXJQYXJ0c10uam9pbignICcpO1xuICAgICAgfSlcbiAgICAgIC5qb2luKCcsICcpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2VsZWN0b3JOZWVkc1Njb3Bpbmcoc2VsZWN0b3I6IHN0cmluZywgc2NvcGVTZWxlY3Rvcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgcmUgPSB0aGlzLl9tYWtlU2NvcGVNYXRjaGVyKHNjb3BlU2VsZWN0b3IpO1xuICAgIHJldHVybiAhcmUudGVzdChzZWxlY3Rvcik7XG4gIH1cblxuICBwcml2YXRlIF9tYWtlU2NvcGVNYXRjaGVyKHNjb3BlU2VsZWN0b3I6IHN0cmluZyk6IFJlZ0V4cCB7XG4gICAgY29uc3QgbHJlID0gL1xcWy9nO1xuICAgIGNvbnN0IHJyZSA9IC9cXF0vZztcbiAgICBzY29wZVNlbGVjdG9yID0gc2NvcGVTZWxlY3Rvci5yZXBsYWNlKGxyZSwgJ1xcXFxbJykucmVwbGFjZShycmUsICdcXFxcXScpO1xuICAgIHJldHVybiBuZXcgUmVnRXhwKCdeKCcgKyBzY29wZVNlbGVjdG9yICsgJyknICsgX3NlbGVjdG9yUmVTdWZmaXgsICdtJyk7XG4gIH1cblxuICAvLyBzY29wZSB2aWEgbmFtZSBhbmQgW2lzPW5hbWVdXG4gIHByaXZhdGUgX2FwcGx5U2ltcGxlU2VsZWN0b3JTY29wZShcbiAgICBzZWxlY3Rvcjogc3RyaW5nLFxuICAgIHNjb3BlU2VsZWN0b3I6IHN0cmluZyxcbiAgICBob3N0U2VsZWN0b3I6IHN0cmluZyxcbiAgKTogc3RyaW5nIHtcbiAgICAvLyBJbiBBbmRyb2lkIGJyb3dzZXIsIHRoZSBsYXN0SW5kZXggaXMgbm90IHJlc2V0IHdoZW4gdGhlIHJlZ2V4IGlzIHVzZWQgaW4gU3RyaW5nLnJlcGxhY2UoKVxuICAgIF9wb2x5ZmlsbEhvc3RSZS5sYXN0SW5kZXggPSAwO1xuICAgIGlmIChfcG9seWZpbGxIb3N0UmUudGVzdChzZWxlY3RvcikpIHtcbiAgICAgIGNvbnN0IHJlcGxhY2VCeSA9IGBbJHtob3N0U2VsZWN0b3J9XWA7XG4gICAgICByZXR1cm4gc2VsZWN0b3JcbiAgICAgICAgLnJlcGxhY2UoX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvclJlLCAoaG5jLCBzZWxlY3RvcikgPT4ge1xuICAgICAgICAgIHJldHVybiBzZWxlY3Rvci5yZXBsYWNlKFxuICAgICAgICAgICAgLyhbXjpdKikoOiopKC4qKS8sXG4gICAgICAgICAgICAoXzogc3RyaW5nLCBiZWZvcmU6IHN0cmluZywgY29sb246IHN0cmluZywgYWZ0ZXI6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gYmVmb3JlICsgcmVwbGFjZUJ5ICsgY29sb24gKyBhZnRlcjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGxhY2UoX3BvbHlmaWxsSG9zdFJlLCByZXBsYWNlQnkgKyAnICcpO1xuICAgIH1cblxuICAgIHJldHVybiBzY29wZVNlbGVjdG9yICsgJyAnICsgc2VsZWN0b3I7XG4gIH1cblxuICAvLyByZXR1cm4gYSBzZWxlY3RvciB3aXRoIFtuYW1lXSBzdWZmaXggb24gZWFjaCBzaW1wbGUgc2VsZWN0b3JcbiAgLy8gZS5nLiAuZm9vLmJhciA+IC56b3QgYmVjb21lcyAuZm9vW25hbWVdLmJhcltuYW1lXSA+IC56b3RbbmFtZV0gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBfYXBwbHlTZWxlY3RvclNjb3BlKFxuICAgIHNlbGVjdG9yOiBzdHJpbmcsXG4gICAgc2NvcGVTZWxlY3Rvcjogc3RyaW5nLFxuICAgIGhvc3RTZWxlY3Rvcjogc3RyaW5nLFxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGlzUmUgPSAvXFxbaXM9KFteXFxdXSopXFxdL2c7XG4gICAgc2NvcGVTZWxlY3RvciA9IHNjb3BlU2VsZWN0b3IucmVwbGFjZShpc1JlLCAoXzogc3RyaW5nLCAuLi5wYXJ0czogc3RyaW5nW10pID0+IHBhcnRzWzBdKTtcblxuICAgIGNvbnN0IGF0dHJOYW1lID0gJ1snICsgc2NvcGVTZWxlY3RvciArICddJztcblxuICAgIGNvbnN0IF9zY29wZVNlbGVjdG9yUGFydCA9IChwOiBzdHJpbmcpID0+IHtcbiAgICAgIGxldCBzY29wZWRQID0gcC50cmltKCk7XG5cbiAgICAgIGlmICghc2NvcGVkUCkge1xuICAgICAgICByZXR1cm4gcDtcbiAgICAgIH1cblxuICAgICAgaWYgKHAuaW5jbHVkZXMoX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvcikpIHtcbiAgICAgICAgc2NvcGVkUCA9IHRoaXMuX2FwcGx5U2ltcGxlU2VsZWN0b3JTY29wZShwLCBzY29wZVNlbGVjdG9yLCBob3N0U2VsZWN0b3IpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVtb3ZlIDpob3N0IHNpbmNlIGl0IHNob3VsZCBiZSB1bm5lY2Vzc2FyeVxuICAgICAgICBjb25zdCB0ID0gcC5yZXBsYWNlKF9wb2x5ZmlsbEhvc3RSZSwgJycpO1xuICAgICAgICBpZiAodC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IHQubWF0Y2goLyhbXjpdKikoOiopKC4qKS8pO1xuICAgICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICBzY29wZWRQID0gbWF0Y2hlc1sxXSArIGF0dHJOYW1lICsgbWF0Y2hlc1syXSArIG1hdGNoZXNbM107XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzY29wZWRQO1xuICAgIH07XG5cbiAgICBjb25zdCBzYWZlQ29udGVudCA9IG5ldyBTYWZlU2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgIHNlbGVjdG9yID0gc2FmZUNvbnRlbnQuY29udGVudCgpO1xuXG4gICAgbGV0IHNjb3BlZFNlbGVjdG9yID0gJyc7XG4gICAgbGV0IHN0YXJ0SW5kZXggPSAwO1xuICAgIGxldCByZXM6IFJlZ0V4cEV4ZWNBcnJheSB8IG51bGw7XG4gICAgY29uc3Qgc2VwID0gLyggfD58XFwrfH4oPyE9KSlcXHMqL2c7XG5cbiAgICAvLyBJZiBhIHNlbGVjdG9yIGFwcGVhcnMgYmVmb3JlIDpob3N0IGl0IHNob3VsZCBub3QgYmUgc2hpbW1lZCBhcyBpdFxuICAgIC8vIG1hdGNoZXMgb24gYW5jZXN0b3IgZWxlbWVudHMgYW5kIG5vdCBvbiBlbGVtZW50cyBpbiB0aGUgaG9zdCdzIHNoYWRvd1xuICAgIC8vIGA6aG9zdC1jb250ZXh0KGRpdilgIGlzIHRyYW5zZm9ybWVkIHRvXG4gICAgLy8gYC1zaGFkb3djc3Nob3N0LW5vLWNvbWJpbmF0b3JkaXYsIGRpdiAtc2hhZG93Y3NzaG9zdC1uby1jb21iaW5hdG9yYFxuICAgIC8vIHRoZSBgZGl2YCBpcyBub3QgcGFydCBvZiB0aGUgY29tcG9uZW50IGluIHRoZSAybmQgc2VsZWN0b3JzIGFuZCBzaG91bGQgbm90IGJlIHNjb3BlZC5cbiAgICAvLyBIaXN0b3JpY2FsbHkgYGNvbXBvbmVudC10YWc6aG9zdGAgd2FzIG1hdGNoaW5nIHRoZSBjb21wb25lbnQgc28gd2UgYWxzbyB3YW50IHRvIHByZXNlcnZlXG4gICAgLy8gdGhpcyBiZWhhdmlvciB0byBhdm9pZCBicmVha2luZyBsZWdhY3kgYXBwcyAoaXQgc2hvdWxkIG5vdCBtYXRjaCkuXG4gICAgLy8gVGhlIGJlaGF2aW9yIHNob3VsZCBiZTpcbiAgICAvLyAtIGB0YWc6aG9zdGAgLT4gYHRhZ1toXWAgKHRoaXMgaXMgdG8gYXZvaWQgYnJlYWtpbmcgbGVnYWN5IGFwcHMsIHNob3VsZCBub3QgbWF0Y2ggYW55dGhpbmcpXG4gICAgLy8gLSBgdGFnIDpob3N0YCAtPiBgdGFnIFtoXWAgKGB0YWdgIGlzIG5vdCBzY29wZWQgYmVjYXVzZSBpdCdzIGNvbnNpZGVyZWQgcGFydCBvZiBhXG4gICAgLy8gICBgOmhvc3QtY29udGV4dCh0YWcpYClcbiAgICBjb25zdCBoYXNIb3N0ID0gc2VsZWN0b3IuaW5jbHVkZXMoX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvcik7XG4gICAgLy8gT25seSBzY29wZSBwYXJ0cyBhZnRlciB0aGUgZmlyc3QgYC1zaGFkb3djc3Nob3N0LW5vLWNvbWJpbmF0b3JgIHdoZW4gaXQgaXMgcHJlc2VudFxuICAgIGxldCBzaG91bGRTY29wZSA9ICFoYXNIb3N0O1xuXG4gICAgd2hpbGUgKChyZXMgPSBzZXAuZXhlYyhzZWxlY3RvcikpICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBzZXBhcmF0b3IgPSByZXNbMV07XG4gICAgICAvLyBEbyBub3QgdHJpbSB0aGUgc2VsZWN0b3IsIGFzIG90aGVyd2lzZSB0aGlzIHdpbGwgYnJlYWsgc291cmNlbWFwc1xuICAgICAgLy8gd2hlbiB0aGV5IGFyZSBkZWZpbmVkIG9uIG11bHRpcGxlIGxpbmVzXG4gICAgICAvLyBFeGFtcGxlOlxuICAgICAgLy8gIGRpdixcbiAgICAgIC8vICBwIHsgY29sb3I6IHJlZH1cbiAgICAgIGNvbnN0IHBhcnQgPSBzZWxlY3Rvci5zbGljZShzdGFydEluZGV4LCByZXMuaW5kZXgpO1xuXG4gICAgICAvLyBBIHNwYWNlIGZvbGxvd2luZyBhbiBlc2NhcGVkIGhleCB2YWx1ZSBhbmQgZm9sbG93ZWQgYnkgYW5vdGhlciBoZXggY2hhcmFjdGVyXG4gICAgICAvLyAoaWU6IFwiLlxcZmMgYmVyXCIgZm9yIFwiLsO8YmVyXCIpIGlzIG5vdCBhIHNlcGFyYXRvciBiZXR3ZWVuIDIgc2VsZWN0b3JzXG4gICAgICAvLyBhbHNvIGtlZXAgaW4gbWluZCB0aGF0IGJhY2tzbGFzaGVzIGFyZSByZXBsYWNlZCBieSBhIHBsYWNlaG9sZGVyIGJ5IFNhZmVTZWxlY3RvclxuICAgICAgLy8gVGhlc2UgZXNjYXBlZCBzZWxlY3RvcnMgaGFwcGVuIGZvciBleGFtcGxlIHdoZW4gZXNidWlsZCBydW5zIHdpdGggb3B0aW1pemF0aW9uLm1pbmlmeS5cbiAgICAgIGlmIChwYXJ0Lm1hdGNoKC9fX2VzYy1waC0oXFxkKylfXy8pICYmIHNlbGVjdG9yW3Jlcy5pbmRleCArIDFdPy5tYXRjaCgvW2EtZkEtRlxcZF0vKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgc2hvdWxkU2NvcGUgPSBzaG91bGRTY29wZSB8fCBwYXJ0LmluY2x1ZGVzKF9wb2x5ZmlsbEhvc3ROb0NvbWJpbmF0b3IpO1xuICAgICAgY29uc3Qgc2NvcGVkUGFydCA9IHNob3VsZFNjb3BlID8gX3Njb3BlU2VsZWN0b3JQYXJ0KHBhcnQpIDogcGFydDtcbiAgICAgIHNjb3BlZFNlbGVjdG9yICs9IGAke3Njb3BlZFBhcnR9ICR7c2VwYXJhdG9yfSBgO1xuICAgICAgc3RhcnRJbmRleCA9IHNlcC5sYXN0SW5kZXg7XG4gICAgfVxuXG4gICAgY29uc3QgcGFydCA9IHNlbGVjdG9yLnN1YnN0cmluZyhzdGFydEluZGV4KTtcbiAgICBzaG91bGRTY29wZSA9IHNob3VsZFNjb3BlIHx8IHBhcnQuaW5jbHVkZXMoX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvcik7XG4gICAgc2NvcGVkU2VsZWN0b3IgKz0gc2hvdWxkU2NvcGUgPyBfc2NvcGVTZWxlY3RvclBhcnQocGFydCkgOiBwYXJ0O1xuXG4gICAgLy8gcmVwbGFjZSB0aGUgcGxhY2Vob2xkZXJzIHdpdGggdGhlaXIgb3JpZ2luYWwgdmFsdWVzXG4gICAgcmV0dXJuIHNhZmVDb250ZW50LnJlc3RvcmUoc2NvcGVkU2VsZWN0b3IpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5zZXJ0UG9seWZpbGxIb3N0SW5Dc3NUZXh0KHNlbGVjdG9yOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBzZWxlY3RvclxuICAgICAgLnJlcGxhY2UoX2NvbG9uSG9zdENvbnRleHRSZSwgX3BvbHlmaWxsSG9zdENvbnRleHQpXG4gICAgICAucmVwbGFjZShfY29sb25Ib3N0UmUsIF9wb2x5ZmlsbEhvc3QpO1xuICB9XG59XG5cbmNsYXNzIFNhZmVTZWxlY3RvciB7XG4gIHByaXZhdGUgcGxhY2Vob2xkZXJzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIGluZGV4ID0gMDtcbiAgcHJpdmF0ZSBfY29udGVudDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHNlbGVjdG9yOiBzdHJpbmcpIHtcbiAgICAvLyBSZXBsYWNlcyBhdHRyaWJ1dGUgc2VsZWN0b3JzIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgIC8vIFRoZSBXUyBpbiBbYXR0cj1cInZhIGx1ZVwiXSB3b3VsZCBvdGhlcndpc2UgYmUgaW50ZXJwcmV0ZWQgYXMgYSBzZWxlY3RvciBzZXBhcmF0b3IuXG4gICAgc2VsZWN0b3IgPSB0aGlzLl9lc2NhcGVSZWdleE1hdGNoZXMoc2VsZWN0b3IsIC8oXFxbW15cXF1dKlxcXSkvZyk7XG5cbiAgICAvLyBDU1MgYWxsb3dzIGZvciBjZXJ0YWluIHNwZWNpYWwgY2hhcmFjdGVycyB0byBiZSB1c2VkIGluIHNlbGVjdG9ycyBpZiB0aGV5J3JlIGVzY2FwZWQuXG4gICAgLy8gRS5nLiBgLmZvbzpibHVlYCB3b24ndCBtYXRjaCBhIGNsYXNzIGNhbGxlZCBgZm9vOmJsdWVgLCBiZWNhdXNlIHRoZSBjb2xvbiBkZW5vdGVzIGFcbiAgICAvLyBwc2V1ZG8tY2xhc3MsIGJ1dCB3cml0aW5nIGAuZm9vXFw6Ymx1ZWAgd2lsbCBtYXRjaCwgYmVjYXVzZSB0aGUgY29sb24gd2FzIGVzY2FwZWQuXG4gICAgLy8gUmVwbGFjZSBhbGwgZXNjYXBlIHNlcXVlbmNlcyAoYFxcYCBmb2xsb3dlZCBieSBhIGNoYXJhY3Rlcikgd2l0aCBhIHBsYWNlaG9sZGVyIHNvXG4gICAgLy8gdGhhdCBvdXIgaGFuZGxpbmcgb2YgcHNldWRvLXNlbGVjdG9ycyBkb2Vzbid0IG1lc3Mgd2l0aCB0aGVtLlxuICAgIC8vIEVzY2FwZWQgY2hhcmFjdGVycyBoYXZlIGEgc3BlY2lmaWMgcGxhY2Vob2xkZXIgc28gdGhleSBjYW4gYmUgZGV0ZWN0ZWQgc2VwYXJhdGVseS5cbiAgICBzZWxlY3RvciA9IHNlbGVjdG9yLnJlcGxhY2UoLyhcXFxcLikvZywgKF8sIGtlZXApID0+IHtcbiAgICAgIGNvbnN0IHJlcGxhY2VCeSA9IGBfX2VzYy1waC0ke3RoaXMuaW5kZXh9X19gO1xuICAgICAgdGhpcy5wbGFjZWhvbGRlcnMucHVzaChrZWVwKTtcbiAgICAgIHRoaXMuaW5kZXgrKztcbiAgICAgIHJldHVybiByZXBsYWNlQnk7XG4gICAgfSk7XG5cbiAgICAvLyBSZXBsYWNlcyB0aGUgZXhwcmVzc2lvbiBpbiBgOm50aC1jaGlsZCgybiArIDEpYCB3aXRoIGEgcGxhY2Vob2xkZXIuXG4gICAgLy8gV1MgYW5kIFwiK1wiIHdvdWxkIG90aGVyd2lzZSBiZSBpbnRlcnByZXRlZCBhcyBzZWxlY3RvciBzZXBhcmF0b3JzLlxuICAgIHRoaXMuX2NvbnRlbnQgPSBzZWxlY3Rvci5yZXBsYWNlKC8oOm50aC1bLVxcd10rKShcXChbXildK1xcKSkvZywgKF8sIHBzZXVkbywgZXhwKSA9PiB7XG4gICAgICBjb25zdCByZXBsYWNlQnkgPSBgX19waC0ke3RoaXMuaW5kZXh9X19gO1xuICAgICAgdGhpcy5wbGFjZWhvbGRlcnMucHVzaChleHApO1xuICAgICAgdGhpcy5pbmRleCsrO1xuICAgICAgcmV0dXJuIHBzZXVkbyArIHJlcGxhY2VCeTtcbiAgICB9KTtcbiAgfVxuXG4gIHJlc3RvcmUoY29udGVudDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29udGVudC5yZXBsYWNlKC9fXyg/OnBofGVzYy1waCktKFxcZCspX18vZywgKF9waCwgaW5kZXgpID0+IHRoaXMucGxhY2Vob2xkZXJzWytpbmRleF0pO1xuICB9XG5cbiAgY29udGVudCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9jb250ZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIGFsbCBvZiB0aGUgc3Vic3RyaW5ncyB0aGF0IG1hdGNoIGEgcmVnZXggd2l0aGluIGFcbiAgICogc3BlY2lhbCBzdHJpbmcgKGUuZy4gYF9fcGgtMF9fYCwgYF9fcGgtMV9fYCwgZXRjKS5cbiAgICovXG4gIHByaXZhdGUgX2VzY2FwZVJlZ2V4TWF0Y2hlcyhjb250ZW50OiBzdHJpbmcsIHBhdHRlcm46IFJlZ0V4cCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNvbnRlbnQucmVwbGFjZShwYXR0ZXJuLCAoXywga2VlcCkgPT4ge1xuICAgICAgY29uc3QgcmVwbGFjZUJ5ID0gYF9fcGgtJHt0aGlzLmluZGV4fV9fYDtcbiAgICAgIHRoaXMucGxhY2Vob2xkZXJzLnB1c2goa2VlcCk7XG4gICAgICB0aGlzLmluZGV4Kys7XG4gICAgICByZXR1cm4gcmVwbGFjZUJ5O1xuICAgIH0pO1xuICB9XG59XG5cbmNvbnN0IF9jc3NDb250ZW50TmV4dFNlbGVjdG9yUmUgPVxuICAvcG9seWZpbGwtbmV4dC1zZWxlY3RvcltefV0qY29udGVudDpbXFxzXSo/KFsnXCJdKSguKj8pXFwxWztcXHNdKn0oW157XSo/KXsvZ2ltO1xuY29uc3QgX2Nzc0NvbnRlbnRSdWxlUmUgPSAvKHBvbHlmaWxsLXJ1bGUpW159XSooY29udGVudDpbXFxzXSooWydcIl0pKC4qPylcXDMpWztcXHNdKltefV0qfS9naW07XG5jb25zdCBfY3NzQ29udGVudFVuc2NvcGVkUnVsZVJlID1cbiAgLyhwb2x5ZmlsbC11bnNjb3BlZC1ydWxlKVtefV0qKGNvbnRlbnQ6W1xcc10qKFsnXCJdKSguKj8pXFwzKVs7XFxzXSpbXn1dKn0vZ2ltO1xuY29uc3QgX3BvbHlmaWxsSG9zdCA9ICctc2hhZG93Y3NzaG9zdCc7XG4vLyBub3RlOiA6aG9zdC1jb250ZXh0IHByZS1wcm9jZXNzZWQgdG8gLXNoYWRvd2Nzc2hvc3Rjb250ZXh0LlxuY29uc3QgX3BvbHlmaWxsSG9zdENvbnRleHQgPSAnLXNoYWRvd2Nzc2NvbnRleHQnO1xuY29uc3QgX3BhcmVuU3VmZml4ID0gJyg/OlxcXFwoKCcgKyAnKD86XFxcXChbXikoXSpcXFxcKXxbXikoXSopKz8nICsgJylcXFxcKSk/KFteLHtdKiknO1xuY29uc3QgX2Nzc0NvbG9uSG9zdFJlID0gbmV3IFJlZ0V4cChfcG9seWZpbGxIb3N0ICsgX3BhcmVuU3VmZml4LCAnZ2ltJyk7XG5jb25zdCBfY3NzQ29sb25Ib3N0Q29udGV4dFJlR2xvYmFsID0gbmV3IFJlZ0V4cChfcG9seWZpbGxIb3N0Q29udGV4dCArIF9wYXJlblN1ZmZpeCwgJ2dpbScpO1xuY29uc3QgX2Nzc0NvbG9uSG9zdENvbnRleHRSZSA9IG5ldyBSZWdFeHAoX3BvbHlmaWxsSG9zdENvbnRleHQgKyBfcGFyZW5TdWZmaXgsICdpbScpO1xuY29uc3QgX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvciA9IF9wb2x5ZmlsbEhvc3QgKyAnLW5vLWNvbWJpbmF0b3InO1xuY29uc3QgX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvclJlID0gLy1zaGFkb3djc3Nob3N0LW5vLWNvbWJpbmF0b3IoW15cXHNdKikvO1xuY29uc3QgX3NoYWRvd0RPTVNlbGVjdG9yc1JlID0gW1xuICAvOjpzaGFkb3cvZyxcbiAgLzo6Y29udGVudC9nLFxuICAvLyBEZXByZWNhdGVkIHNlbGVjdG9yc1xuICAvXFwvc2hhZG93LWRlZXBcXC8vZyxcbiAgL1xcL3NoYWRvd1xcLy9nLFxuXTtcblxuLy8gVGhlIGRlZXAgY29tYmluYXRvciBpcyBkZXByZWNhdGVkIGluIHRoZSBDU1Mgc3BlY1xuLy8gU3VwcG9ydCBmb3IgYD4+PmAsIGBkZWVwYCwgYDo6bmctZGVlcGAgaXMgdGhlbiBhbHNvIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgZnV0dXJlLlxuLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvcHVsbC8xNzY3N1xuY29uc3QgX3NoYWRvd0RlZXBTZWxlY3RvcnMgPSAvKD86Pj4+KXwoPzpcXC9kZWVwXFwvKXwoPzo6Om5nLWRlZXApL2c7XG5jb25zdCBfc2VsZWN0b3JSZVN1ZmZpeCA9ICcoWz5cXFxcc34rWy4sezpdW1xcXFxzXFxcXFNdKik/JCc7XG5jb25zdCBfcG9seWZpbGxIb3N0UmUgPSAvLXNoYWRvd2Nzc2hvc3QvZ2ltO1xuY29uc3QgX2NvbG9uSG9zdFJlID0gLzpob3N0L2dpbTtcbmNvbnN0IF9jb2xvbkhvc3RDb250ZXh0UmUgPSAvOmhvc3QtY29udGV4dC9naW07XG5cbmNvbnN0IF9uZXdMaW5lc1JlID0gL1xccj9cXG4vZztcbmNvbnN0IF9jb21tZW50UmUgPSAvXFwvXFwqW1xcc1xcU10qP1xcKlxcLy9nO1xuY29uc3QgX2NvbW1lbnRXaXRoSGFzaFJlID0gL1xcL1xcKlxccyojXFxzKnNvdXJjZShNYXBwaW5nKT9VUkw9L2c7XG5jb25zdCBDT01NRU5UX1BMQUNFSE9MREVSID0gJyVDT01NRU5UJSc7XG5jb25zdCBfY29tbWVudFdpdGhIYXNoUGxhY2VIb2xkZXJSZSA9IG5ldyBSZWdFeHAoQ09NTUVOVF9QTEFDRUhPTERFUiwgJ2cnKTtcblxuY29uc3QgQkxPQ0tfUExBQ0VIT0xERVIgPSAnJUJMT0NLJSc7XG5jb25zdCBfcnVsZVJlID0gbmV3IFJlZ0V4cChcbiAgYChcXFxccyooPzoke0NPTU1FTlRfUExBQ0VIT0xERVJ9XFxcXHMqKSopKFteO1xcXFx7XFxcXH1dKz8pKFxcXFxzKikoKD86eyVCTE9DSyV9P1xcXFxzKjs/KXwoPzpcXFxccyo7KSlgLFxuICAnZycsXG4pO1xuY29uc3QgQ09OVEVOVF9QQUlSUyA9IG5ldyBNYXAoW1sneycsICd9J11dKTtcblxuY29uc3QgQ09NTUFfSU5fUExBQ0VIT0xERVIgPSAnJUNPTU1BX0lOX1BMQUNFSE9MREVSJSc7XG5jb25zdCBTRU1JX0lOX1BMQUNFSE9MREVSID0gJyVTRU1JX0lOX1BMQUNFSE9MREVSJSc7XG5jb25zdCBDT0xPTl9JTl9QTEFDRUhPTERFUiA9ICclQ09MT05fSU5fUExBQ0VIT0xERVIlJztcblxuY29uc3QgX2Nzc0NvbW1hSW5QbGFjZWhvbGRlclJlR2xvYmFsID0gbmV3IFJlZ0V4cChDT01NQV9JTl9QTEFDRUhPTERFUiwgJ2cnKTtcbmNvbnN0IF9jc3NTZW1pSW5QbGFjZWhvbGRlclJlR2xvYmFsID0gbmV3IFJlZ0V4cChTRU1JX0lOX1BMQUNFSE9MREVSLCAnZycpO1xuY29uc3QgX2Nzc0NvbG9uSW5QbGFjZWhvbGRlclJlR2xvYmFsID0gbmV3IFJlZ0V4cChDT0xPTl9JTl9QTEFDRUhPTERFUiwgJ2cnKTtcblxuZXhwb3J0IGNsYXNzIENzc1J1bGUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgc2VsZWN0b3I6IHN0cmluZyxcbiAgICBwdWJsaWMgY29udGVudDogc3RyaW5nLFxuICApIHt9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9jZXNzUnVsZXMoaW5wdXQ6IHN0cmluZywgcnVsZUNhbGxiYWNrOiAocnVsZTogQ3NzUnVsZSkgPT4gQ3NzUnVsZSk6IHN0cmluZyB7XG4gIGNvbnN0IGVzY2FwZWQgPSBlc2NhcGVJblN0cmluZ3MoaW5wdXQpO1xuICBjb25zdCBpbnB1dFdpdGhFc2NhcGVkQmxvY2tzID0gZXNjYXBlQmxvY2tzKGVzY2FwZWQsIENPTlRFTlRfUEFJUlMsIEJMT0NLX1BMQUNFSE9MREVSKTtcbiAgbGV0IG5leHRCbG9ja0luZGV4ID0gMDtcbiAgY29uc3QgZXNjYXBlZFJlc3VsdCA9IGlucHV0V2l0aEVzY2FwZWRCbG9ja3MuZXNjYXBlZFN0cmluZy5yZXBsYWNlKF9ydWxlUmUsICguLi5tOiBzdHJpbmdbXSkgPT4ge1xuICAgIGNvbnN0IHNlbGVjdG9yID0gbVsyXTtcbiAgICBsZXQgY29udGVudCA9ICcnO1xuICAgIGxldCBzdWZmaXggPSBtWzRdO1xuICAgIGxldCBjb250ZW50UHJlZml4ID0gJyc7XG4gICAgaWYgKHN1ZmZpeCAmJiBzdWZmaXguc3RhcnRzV2l0aCgneycgKyBCTE9DS19QTEFDRUhPTERFUikpIHtcbiAgICAgIGNvbnRlbnQgPSBpbnB1dFdpdGhFc2NhcGVkQmxvY2tzLmJsb2Nrc1tuZXh0QmxvY2tJbmRleCsrXTtcbiAgICAgIHN1ZmZpeCA9IHN1ZmZpeC5zdWJzdHJpbmcoQkxPQ0tfUExBQ0VIT0xERVIubGVuZ3RoICsgMSk7XG4gICAgICBjb250ZW50UHJlZml4ID0gJ3snO1xuICAgIH1cbiAgICBjb25zdCBydWxlID0gcnVsZUNhbGxiYWNrKG5ldyBDc3NSdWxlKHNlbGVjdG9yLCBjb250ZW50KSk7XG4gICAgcmV0dXJuIGAke21bMV19JHtydWxlLnNlbGVjdG9yfSR7bVszXX0ke2NvbnRlbnRQcmVmaXh9JHtydWxlLmNvbnRlbnR9JHtzdWZmaXh9YDtcbiAgfSk7XG4gIHJldHVybiB1bmVzY2FwZUluU3RyaW5ncyhlc2NhcGVkUmVzdWx0KTtcbn1cblxuY2xhc3MgU3RyaW5nV2l0aEVzY2FwZWRCbG9ja3Mge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgZXNjYXBlZFN0cmluZzogc3RyaW5nLFxuICAgIHB1YmxpYyBibG9ja3M6IHN0cmluZ1tdLFxuICApIHt9XG59XG5cbmZ1bmN0aW9uIGVzY2FwZUJsb2NrcyhcbiAgaW5wdXQ6IHN0cmluZyxcbiAgY2hhclBhaXJzOiBNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBwbGFjZWhvbGRlcjogc3RyaW5nLFxuKTogU3RyaW5nV2l0aEVzY2FwZWRCbG9ja3Mge1xuICBjb25zdCByZXN1bHRQYXJ0czogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgZXNjYXBlZEJsb2Nrczogc3RyaW5nW10gPSBbXTtcbiAgbGV0IG9wZW5DaGFyQ291bnQgPSAwO1xuICBsZXQgbm9uQmxvY2tTdGFydEluZGV4ID0gMDtcbiAgbGV0IGJsb2NrU3RhcnRJbmRleCA9IC0xO1xuICBsZXQgb3BlbkNoYXI6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IGNsb3NlQ2hhcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjaGFyID0gaW5wdXRbaV07XG4gICAgaWYgKGNoYXIgPT09ICdcXFxcJykge1xuICAgICAgaSsrO1xuICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gY2xvc2VDaGFyKSB7XG4gICAgICBvcGVuQ2hhckNvdW50LS07XG4gICAgICBpZiAob3BlbkNoYXJDb3VudCA9PT0gMCkge1xuICAgICAgICBlc2NhcGVkQmxvY2tzLnB1c2goaW5wdXQuc3Vic3RyaW5nKGJsb2NrU3RhcnRJbmRleCwgaSkpO1xuICAgICAgICByZXN1bHRQYXJ0cy5wdXNoKHBsYWNlaG9sZGVyKTtcbiAgICAgICAgbm9uQmxvY2tTdGFydEluZGV4ID0gaTtcbiAgICAgICAgYmxvY2tTdGFydEluZGV4ID0gLTE7XG4gICAgICAgIG9wZW5DaGFyID0gY2xvc2VDaGFyID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gb3BlbkNoYXIpIHtcbiAgICAgIG9wZW5DaGFyQ291bnQrKztcbiAgICB9IGVsc2UgaWYgKG9wZW5DaGFyQ291bnQgPT09IDAgJiYgY2hhclBhaXJzLmhhcyhjaGFyKSkge1xuICAgICAgb3BlbkNoYXIgPSBjaGFyO1xuICAgICAgY2xvc2VDaGFyID0gY2hhclBhaXJzLmdldChjaGFyKTtcbiAgICAgIG9wZW5DaGFyQ291bnQgPSAxO1xuICAgICAgYmxvY2tTdGFydEluZGV4ID0gaSArIDE7XG4gICAgICByZXN1bHRQYXJ0cy5wdXNoKGlucHV0LnN1YnN0cmluZyhub25CbG9ja1N0YXJ0SW5kZXgsIGJsb2NrU3RhcnRJbmRleCkpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChibG9ja1N0YXJ0SW5kZXggIT09IC0xKSB7XG4gICAgZXNjYXBlZEJsb2Nrcy5wdXNoKGlucHV0LnN1YnN0cmluZyhibG9ja1N0YXJ0SW5kZXgpKTtcbiAgICByZXN1bHRQYXJ0cy5wdXNoKHBsYWNlaG9sZGVyKTtcbiAgfSBlbHNlIHtcbiAgICByZXN1bHRQYXJ0cy5wdXNoKGlucHV0LnN1YnN0cmluZyhub25CbG9ja1N0YXJ0SW5kZXgpKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgU3RyaW5nV2l0aEVzY2FwZWRCbG9ja3MocmVzdWx0UGFydHMuam9pbignJyksIGVzY2FwZWRCbG9ja3MpO1xufVxuXG4vKipcbiAqIE9iamVjdCBjb250YWluaW5nIGFzIGtleXMgY2hhcmFjdGVycyB0aGF0IHNob3VsZCBiZSBzdWJzdGl0dXRlZCBieSBwbGFjZWhvbGRlcnNcbiAqIHdoZW4gZm91bmQgaW4gc3RyaW5ncyBkdXJpbmcgdGhlIGNzcyB0ZXh0IHBhcnNpbmcsIGFuZCBhcyB2YWx1ZXMgdGhlIHJlc3BlY3RpdmVcbiAqIHBsYWNlaG9sZGVyc1xuICovXG5jb25zdCBFU0NBUEVfSU5fU1RSSU5HX01BUDoge1trZXk6IHN0cmluZ106IHN0cmluZ30gPSB7XG4gICc7JzogU0VNSV9JTl9QTEFDRUhPTERFUixcbiAgJywnOiBDT01NQV9JTl9QTEFDRUhPTERFUixcbiAgJzonOiBDT0xPTl9JTl9QTEFDRUhPTERFUixcbn07XG5cbi8qKlxuICogUGFyc2UgdGhlIHByb3ZpZGVkIGNzcyB0ZXh0IGFuZCBpbnNpZGUgc3RyaW5ncyAobWVhbmluZywgaW5zaWRlIHBhaXJzIG9mIHVuZXNjYXBlZCBzaW5nbGUgb3JcbiAqIGRvdWJsZSBxdW90ZXMpIHJlcGxhY2Ugc3BlY2lmaWMgY2hhcmFjdGVycyB3aXRoIHRoZWlyIHJlc3BlY3RpdmUgcGxhY2Vob2xkZXJzIGFzIGluZGljYXRlZFxuICogYnkgdGhlIGBFU0NBUEVfSU5fU1RSSU5HX01BUGAgbWFwLlxuICpcbiAqIEZvciBleGFtcGxlIGNvbnZlcnQgdGhlIHRleHRcbiAqICBgYW5pbWF0aW9uOiBcIm15LWFuaW06YXRcXFwiaW9uXCIgMXM7YFxuICogdG9cbiAqICBgYW5pbWF0aW9uOiBcIm15LWFuaW0lQ09MT05fSU5fUExBQ0VIT0xERVIlYXRcXFwiaW9uXCIgMXM7YFxuICpcbiAqIFRoaXMgaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIHJlbW92ZSB0aGUgbWVhbmluZyBvZiBzb21lIGNoYXJhY3RlcnMgd2hlbiBmb3VuZCBpbnNpZGUgc3RyaW5nc1xuICogKGZvciBleGFtcGxlIGA7YCBpbmRpY2F0ZXMgdGhlIGVuZCBvZiBhIGNzcyBkZWNsYXJhdGlvbiwgYCxgIHRoZSBzZXF1ZW5jZSBvZiB2YWx1ZXMgYW5kIGA6YCB0aGVcbiAqIGRpdmlzaW9uIGJldHdlZW4gcHJvcGVydHkgYW5kIHZhbHVlIGR1cmluZyBhIGRlY2xhcmF0aW9uLCBub25lIG9mIHRoZXNlIG1lYW5pbmdzIGFwcGx5IHdoZW4gc3VjaFxuICogY2hhcmFjdGVycyBhcmUgd2l0aGluIHN0cmluZ3MgYW5kIHNvIGluIG9yZGVyIHRvIHByZXZlbnQgcGFyc2luZyBpc3N1ZXMgdGhleSBuZWVkIHRvIGJlIHJlcGxhY2VkXG4gKiB3aXRoIHBsYWNlaG9sZGVyIHRleHQgZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGUgY3NzIG1hbmlwdWxhdGlvbiBwcm9jZXNzKS5cbiAqXG4gKiBAcGFyYW0gaW5wdXQgdGhlIG9yaWdpbmFsIGNzcyB0ZXh0LlxuICpcbiAqIEByZXR1cm5zIHRoZSBjc3MgdGV4dCB3aXRoIHNwZWNpZmljIGNoYXJhY3RlcnMgaW4gc3RyaW5ncyByZXBsYWNlZCBieSBwbGFjZWhvbGRlcnMuXG4gKiovXG5mdW5jdGlvbiBlc2NhcGVJblN0cmluZ3MoaW5wdXQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCByZXN1bHQgPSBpbnB1dDtcbiAgbGV0IGN1cnJlbnRRdW90ZUNoYXI6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdC5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGNoYXIgPSByZXN1bHRbaV07XG4gICAgaWYgKGNoYXIgPT09ICdcXFxcJykge1xuICAgICAgaSsrO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoY3VycmVudFF1b3RlQ2hhciAhPT0gbnVsbCkge1xuICAgICAgICAvLyBpbmRleCBpIGlzIGluc2lkZSBhIHF1b3RlZCBzdWItc3RyaW5nXG4gICAgICAgIGlmIChjaGFyID09PSBjdXJyZW50UXVvdGVDaGFyKSB7XG4gICAgICAgICAgY3VycmVudFF1b3RlQ2hhciA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgcGxhY2Vob2xkZXI6IHN0cmluZyB8IHVuZGVmaW5lZCA9IEVTQ0FQRV9JTl9TVFJJTkdfTUFQW2NoYXJdO1xuICAgICAgICAgIGlmIChwbGFjZWhvbGRlcikge1xuICAgICAgICAgICAgcmVzdWx0ID0gYCR7cmVzdWx0LnN1YnN0cigwLCBpKX0ke3BsYWNlaG9sZGVyfSR7cmVzdWx0LnN1YnN0cihpICsgMSl9YDtcbiAgICAgICAgICAgIGkgKz0gcGxhY2Vob2xkZXIubGVuZ3RoIC0gMTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gXCInXCIgfHwgY2hhciA9PT0gJ1wiJykge1xuICAgICAgICBjdXJyZW50UXVvdGVDaGFyID0gY2hhcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBSZXBsYWNlIGluIGEgc3RyaW5nIGFsbCBvY2N1cnJlbmNlcyBvZiBrZXlzIGluIHRoZSBgRVNDQVBFX0lOX1NUUklOR19NQVBgIG1hcCB3aXRoIHRoZWlyXG4gKiBvcmlnaW5hbCByZXByZXNlbnRhdGlvbiwgdGhpcyBpcyBzaW1wbHkgdXNlZCB0byByZXZlcnQgdGhlIGNoYW5nZXMgYXBwbGllZCBieSB0aGVcbiAqIGVzY2FwZUluU3RyaW5ncyBmdW5jdGlvbi5cbiAqXG4gKiBGb3IgZXhhbXBsZSBpdCByZXZlcnRzIHRoZSB0ZXh0OlxuICogIGBhbmltYXRpb246IFwibXktYW5pbSVDT0xPTl9JTl9QTEFDRUhPTERFUiVhdFxcXCJpb25cIiAxcztgXG4gKiB0byBpdCdzIG9yaWdpbmFsIGZvcm0gb2Y6XG4gKiAgYGFuaW1hdGlvbjogXCJteS1hbmltOmF0XFxcImlvblwiIDFzO2BcbiAqXG4gKiBOb3RlOiBGb3IgdGhlIHNha2Ugb2Ygc2ltcGxpY2l0eSB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGNoZWNrIHRoYXQgdGhlIHBsYWNlaG9sZGVycyBhcmVcbiAqIGFjdHVhbGx5IGluc2lkZSBzdHJpbmdzIGFzIGl0IHdvdWxkIGFueXdheSBiZSBleHRyZW1lbHkgdW5saWtlbHkgdG8gZmluZCB0aGVtIG91dHNpZGUgb2Ygc3RyaW5ncy5cbiAqXG4gKiBAcGFyYW0gaW5wdXQgdGhlIGNzcyB0ZXh0IGNvbnRhaW5pbmcgdGhlIHBsYWNlaG9sZGVycy5cbiAqXG4gKiBAcmV0dXJucyB0aGUgY3NzIHRleHQgd2l0aG91dCB0aGUgcGxhY2Vob2xkZXJzLlxuICovXG5mdW5jdGlvbiB1bmVzY2FwZUluU3RyaW5ncyhpbnB1dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IHJlc3VsdCA9IGlucHV0LnJlcGxhY2UoX2Nzc0NvbW1hSW5QbGFjZWhvbGRlclJlR2xvYmFsLCAnLCcpO1xuICByZXN1bHQgPSByZXN1bHQucmVwbGFjZShfY3NzU2VtaUluUGxhY2Vob2xkZXJSZUdsb2JhbCwgJzsnKTtcbiAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoX2Nzc0NvbG9uSW5QbGFjZWhvbGRlclJlR2xvYmFsLCAnOicpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFVuZXNjYXBlIGFsbCBxdW90ZXMgcHJlc2VudCBpbiBhIHN0cmluZywgYnV0IG9ubHkgaWYgdGhlIHN0cmluZyB3YXMgYWN0dWFsbHkgYWxyZWFkeVxuICogcXVvdGVkLlxuICpcbiAqIFRoaXMgZ2VuZXJhdGVzIGEgXCJjYW5vbmljYWxcIiByZXByZXNlbnRhdGlvbiBvZiBzdHJpbmdzIHdoaWNoIGNhbiBiZSB1c2VkIHRvIG1hdGNoIHN0cmluZ3NcbiAqIHdoaWNoIHdvdWxkIG90aGVyd2lzZSBvbmx5IGRpZmZlciBiZWNhdXNlIG9mIGRpZmZlcmVudGx5IGVzY2FwZWQgcXVvdGVzLlxuICpcbiAqIEZvciBleGFtcGxlIGl0IGNvbnZlcnRzIHRoZSBzdHJpbmcgKGFzc3VtZWQgdG8gYmUgcXVvdGVkKTpcbiAqICBgdGhpcyBcXFxcXCJpc1xcXFxcIiBhIFxcXFwnXFxcXFxcXFwndGVzdGBcbiAqIHRvOlxuICogIGB0aGlzIFwiaXNcIiBhICdcXFxcXFxcXCd0ZXN0YFxuICogKG5vdGUgdGhhdCB0aGUgbGF0dGVyIGJhY2tzbGFzaGVzIGFyZSBub3QgcmVtb3ZlZCBhcyB0aGV5IGFyZSBub3QgYWN0dWFsbHkgZXNjYXBpbmcgdGhlIHNpbmdsZVxuICogcXVvdGUpXG4gKlxuICpcbiAqIEBwYXJhbSBpbnB1dCB0aGUgc3RyaW5nIHBvc3NpYmx5IGNvbnRhaW5pbmcgZXNjYXBlZCBxdW90ZXMuXG4gKiBAcGFyYW0gaXNRdW90ZWQgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHN0cmluZyB3YXMgcXVvdGVkIGluc2lkZSBhIGJpZ2dlciBzdHJpbmcgKGlmIG5vdFxuICogdGhlbiBpdCBtZWFucyB0aGF0IGl0IGRvZXNuJ3QgcmVwcmVzZW50IGFuIGlubmVyIHN0cmluZyBhbmQgdGh1cyBubyB1bmVzY2FwaW5nIGlzIHJlcXVpcmVkKVxuICpcbiAqIEByZXR1cm5zIHRoZSBzdHJpbmcgaW4gdGhlIFwiY2Fub25pY2FsXCIgcmVwcmVzZW50YXRpb24gd2l0aG91dCBlc2NhcGVkIHF1b3Rlcy5cbiAqL1xuZnVuY3Rpb24gdW5lc2NhcGVRdW90ZXMoc3RyOiBzdHJpbmcsIGlzUXVvdGVkOiBib29sZWFuKTogc3RyaW5nIHtcbiAgcmV0dXJuICFpc1F1b3RlZCA/IHN0ciA6IHN0ci5yZXBsYWNlKC8oKD86XnxbXlxcXFxdKSg/OlxcXFxcXFxcKSopXFxcXCg/PVsnXCJdKS9nLCAnJDEnKTtcbn1cblxuLyoqXG4gKiBDb21iaW5lIHRoZSBgY29udGV4dFNlbGVjdG9yc2Agd2l0aCB0aGUgYGhvc3RNYXJrZXJgIGFuZCB0aGUgYG90aGVyU2VsZWN0b3JzYFxuICogdG8gY3JlYXRlIGEgc2VsZWN0b3IgdGhhdCBtYXRjaGVzIHRoZSBzYW1lIGFzIGA6aG9zdC1jb250ZXh0KClgLlxuICpcbiAqIEdpdmVuIGEgc2luZ2xlIGNvbnRleHQgc2VsZWN0b3IgYEFgIHdlIG5lZWQgdG8gb3V0cHV0IHNlbGVjdG9ycyB0aGF0IG1hdGNoIG9uIHRoZSBob3N0IGFuZCBhcyBhblxuICogYW5jZXN0b3Igb2YgdGhlIGhvc3Q6XG4gKlxuICogYGBgXG4gKiBBIDxob3N0TWFya2VyPiwgQTxob3N0TWFya2VyPiB7fVxuICogYGBgXG4gKlxuICogV2hlbiB0aGVyZSBpcyBtb3JlIHRoYW4gb25lIGNvbnRleHQgc2VsZWN0b3Igd2UgYWxzbyBoYXZlIHRvIGNyZWF0ZSBjb21iaW5hdGlvbnMgb2YgdGhvc2VcbiAqIHNlbGVjdG9ycyB3aXRoIGVhY2ggb3RoZXIuIEZvciBleGFtcGxlIGlmIHRoZXJlIGFyZSBgQWAgYW5kIGBCYCBzZWxlY3RvcnMgdGhlIG91dHB1dCBpczpcbiAqXG4gKiBgYGBcbiAqIEFCPGhvc3RNYXJrZXI+LCBBQiA8aG9zdE1hcmtlcj4sIEEgQjxob3N0TWFya2VyPixcbiAqIEIgQTxob3N0TWFya2VyPiwgQSBCIDxob3N0TWFya2VyPiwgQiBBIDxob3N0TWFya2VyPiB7fVxuICogYGBgXG4gKlxuICogQW5kIHNvIG9uLi4uXG4gKlxuICogQHBhcmFtIGNvbnRleHRTZWxlY3RvcnMgYW4gYXJyYXkgb2YgY29udGV4dCBzZWxlY3RvcnMgdGhhdCB3aWxsIGJlIGNvbWJpbmVkLlxuICogQHBhcmFtIG90aGVyU2VsZWN0b3JzIHRoZSByZXN0IG9mIHRoZSBzZWxlY3RvcnMgdGhhdCBhcmUgbm90IGNvbnRleHQgc2VsZWN0b3JzLlxuICovXG5mdW5jdGlvbiBjb21iaW5lSG9zdENvbnRleHRTZWxlY3RvcnMoY29udGV4dFNlbGVjdG9yczogc3RyaW5nW10sIG90aGVyU2VsZWN0b3JzOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBob3N0TWFya2VyID0gX3BvbHlmaWxsSG9zdE5vQ29tYmluYXRvcjtcbiAgX3BvbHlmaWxsSG9zdFJlLmxhc3RJbmRleCA9IDA7IC8vIHJlc2V0IHRoZSByZWdleCB0byBlbnN1cmUgd2UgZ2V0IGFuIGFjY3VyYXRlIHRlc3RcbiAgY29uc3Qgb3RoZXJTZWxlY3RvcnNIYXNIb3N0ID0gX3BvbHlmaWxsSG9zdFJlLnRlc3Qob3RoZXJTZWxlY3RvcnMpO1xuXG4gIC8vIElmIHRoZXJlIGFyZSBubyBjb250ZXh0IHNlbGVjdG9ycyB0aGVuIGp1c3Qgb3V0cHV0IGEgaG9zdCBtYXJrZXJcbiAgaWYgKGNvbnRleHRTZWxlY3RvcnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGhvc3RNYXJrZXIgKyBvdGhlclNlbGVjdG9ycztcbiAgfVxuXG4gIGNvbnN0IGNvbWJpbmVkOiBzdHJpbmdbXSA9IFtjb250ZXh0U2VsZWN0b3JzLnBvcCgpIHx8ICcnXTtcbiAgd2hpbGUgKGNvbnRleHRTZWxlY3RvcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGxlbmd0aCA9IGNvbWJpbmVkLmxlbmd0aDtcbiAgICBjb25zdCBjb250ZXh0U2VsZWN0b3IgPSBjb250ZXh0U2VsZWN0b3JzLnBvcCgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHByZXZpb3VzU2VsZWN0b3JzID0gY29tYmluZWRbaV07XG4gICAgICAvLyBBZGQgdGhlIG5ldyBzZWxlY3RvciBhcyBhIGRlc2NlbmRhbnQgb2YgdGhlIHByZXZpb3VzIHNlbGVjdG9yc1xuICAgICAgY29tYmluZWRbbGVuZ3RoICogMiArIGldID0gcHJldmlvdXNTZWxlY3RvcnMgKyAnICcgKyBjb250ZXh0U2VsZWN0b3I7XG4gICAgICAvLyBBZGQgdGhlIG5ldyBzZWxlY3RvciBhcyBhbiBhbmNlc3RvciBvZiB0aGUgcHJldmlvdXMgc2VsZWN0b3JzXG4gICAgICBjb21iaW5lZFtsZW5ndGggKyBpXSA9IGNvbnRleHRTZWxlY3RvciArICcgJyArIHByZXZpb3VzU2VsZWN0b3JzO1xuICAgICAgLy8gQWRkIHRoZSBuZXcgc2VsZWN0b3IgdG8gYWN0IG9uIHRoZSBzYW1lIGVsZW1lbnQgYXMgdGhlIHByZXZpb3VzIHNlbGVjdG9yc1xuICAgICAgY29tYmluZWRbaV0gPSBjb250ZXh0U2VsZWN0b3IgKyBwcmV2aW91c1NlbGVjdG9ycztcbiAgICB9XG4gIH1cbiAgLy8gRmluYWxseSBjb25uZWN0IHRoZSBzZWxlY3RvciB0byB0aGUgYGhvc3RNYXJrZXJgczogZWl0aGVyIGFjdGluZyBkaXJlY3RseSBvbiB0aGUgaG9zdFxuICAvLyAoQTxob3N0TWFya2VyPikgb3IgYXMgYW4gYW5jZXN0b3IgKEEgPGhvc3RNYXJrZXI+KS5cbiAgcmV0dXJuIGNvbWJpbmVkXG4gICAgLm1hcCgocykgPT5cbiAgICAgIG90aGVyU2VsZWN0b3JzSGFzSG9zdFxuICAgICAgICA/IGAke3N9JHtvdGhlclNlbGVjdG9yc31gXG4gICAgICAgIDogYCR7c30ke2hvc3RNYXJrZXJ9JHtvdGhlclNlbGVjdG9yc30sICR7c30gJHtob3N0TWFya2VyfSR7b3RoZXJTZWxlY3RvcnN9YCxcbiAgICApXG4gICAgLmpvaW4oJywnKTtcbn1cblxuLyoqXG4gKiBNdXRhdGUgdGhlIGdpdmVuIGBncm91cHNgIGFycmF5IHNvIHRoYXQgdGhlcmUgYXJlIGBtdWx0aXBsZXNgIGNsb25lcyBvZiB0aGUgb3JpZ2luYWwgYXJyYXlcbiAqIHN0b3JlZC5cbiAqXG4gKiBGb3IgZXhhbXBsZSBgcmVwZWF0R3JvdXBzKFthLCBiXSwgMylgIHdpbGwgcmVzdWx0IGluIGBbYSwgYiwgYSwgYiwgYSwgYl1gIC0gYnV0IGltcG9ydGFudGx5IHRoZVxuICogbmV3bHkgYWRkZWQgZ3JvdXBzIHdpbGwgYmUgY2xvbmVzIG9mIHRoZSBvcmlnaW5hbC5cbiAqXG4gKiBAcGFyYW0gZ3JvdXBzIEFuIGFycmF5IG9mIGdyb3VwcyBvZiBzdHJpbmdzIHRoYXQgd2lsbCBiZSByZXBlYXRlZC4gVGhpcyBhcnJheSBpcyBtdXRhdGVkXG4gKiAgICAgaW4tcGxhY2UuXG4gKiBAcGFyYW0gbXVsdGlwbGVzIFRoZSBudW1iZXIgb2YgdGltZXMgdGhlIGN1cnJlbnQgZ3JvdXBzIHNob3VsZCBhcHBlYXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXBlYXRHcm91cHMoZ3JvdXBzOiBzdHJpbmdbXVtdLCBtdWx0aXBsZXM6IG51bWJlcik6IHZvaWQge1xuICBjb25zdCBsZW5ndGggPSBncm91cHMubGVuZ3RoO1xuICBmb3IgKGxldCBpID0gMTsgaSA8IG11bHRpcGxlczsgaSsrKSB7XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7IGorKykge1xuICAgICAgZ3JvdXBzW2ogKyBpICogbGVuZ3RoXSA9IGdyb3Vwc1tqXS5zbGljZSgwKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==