valtech-components 2.0.305 → 2.0.307

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.
@@ -0,0 +1,469 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, Input } from '@angular/core';
3
+ import { ButtonComponent } from '../../atoms/button/button.component';
4
+ import { ImageComponent } from '../../atoms/image/image.component';
5
+ import { TextComponent } from '../../atoms/text/text.component';
6
+ import { TitleComponent } from '../../atoms/title/title.component';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ /**
10
+ * val-article
11
+ *
12
+ * Componente para crear artículos, blogs y documentación de forma declarativa.
13
+ * Permite combinar múltiples elementos (títulos, texto, imágenes, código, etc.)
14
+ * con espaciado automático y soporte multi-idioma.
15
+ *
16
+ * @example Uso básico:
17
+ * ```html
18
+ * <val-article [props]="articleConfig"></val-article>
19
+ * ```
20
+ *
21
+ * @example Con ArticleBuilder:
22
+ * ```typescript
23
+ * articleConfig = new ArticleBuilder()
24
+ * .title(titleProps)
25
+ * .paragraph(textProps)
26
+ * .code('console.log("Hello World")', 'javascript')
27
+ * .build();
28
+ * ```
29
+ *
30
+ * @input props: ArticleMetadata - Configuración completa del artículo
31
+ */
32
+ export class ArticleComponent {
33
+ constructor() { }
34
+ ngOnInit() {
35
+ // Validación básica
36
+ if (!this.props || !this.props.elements) {
37
+ console.warn('val-article: props.elements is required');
38
+ }
39
+ }
40
+ /**
41
+ * Función de trackBy para optimizar el rendering de elementos
42
+ */
43
+ trackByFn(index, element) {
44
+ return element.id || index;
45
+ }
46
+ /**
47
+ * Obtiene las clases CSS para el espaciado del elemento
48
+ */
49
+ getElementSpacingClass(element) {
50
+ const spacing = element.spacing || this.props.defaultSpacing;
51
+ const classes = [];
52
+ if (spacing?.top) {
53
+ classes.push(`val-article__spacing-top--${spacing.top}`);
54
+ }
55
+ if (spacing?.bottom) {
56
+ classes.push(`val-article__spacing-bottom--${spacing.bottom}`);
57
+ }
58
+ if (spacing?.horizontal) {
59
+ classes.push(`val-article__spacing-horizontal--${spacing.horizontal}`);
60
+ }
61
+ return classes.join(' ');
62
+ }
63
+ // === FUNCIONES DE TIPO PARA TYPESCRIPT ===
64
+ getTitleElement(element) {
65
+ return element;
66
+ }
67
+ getSubtitleElement(element) {
68
+ return element;
69
+ }
70
+ getTextElement(element) {
71
+ return element;
72
+ }
73
+ getQuoteElement(element) {
74
+ return element;
75
+ }
76
+ getHighlightElement(element) {
77
+ return element;
78
+ }
79
+ getCodeElement(element) {
80
+ return element;
81
+ }
82
+ getListElement(element) {
83
+ return element;
84
+ }
85
+ getButtonElement(element) {
86
+ return element;
87
+ }
88
+ getSeparatorElement(element) {
89
+ return element;
90
+ }
91
+ getImageElement(element) {
92
+ return element;
93
+ }
94
+ getVideoElement(element) {
95
+ return element;
96
+ }
97
+ getCustomElement(element) {
98
+ return element;
99
+ }
100
+ // === FUNCIONES AUXILIARES PARA PROPS ===
101
+ getQuoteTextProps(element) {
102
+ const quoteElement = this.getQuoteElement(element);
103
+ const { author, source, ...textProps } = quoteElement.props;
104
+ return textProps;
105
+ }
106
+ getHighlightTextProps(element) {
107
+ const highlightElement = this.getHighlightElement(element);
108
+ const { backgroundColor, rounded, ...textProps } = highlightElement.props;
109
+ return textProps;
110
+ }
111
+ getHighlightColor(element) {
112
+ const highlightElement = this.getHighlightElement(element);
113
+ return highlightElement.props.backgroundColor || 'var(--ion-color-light)';
114
+ }
115
+ getButtonProps(element) {
116
+ const buttonElement = this.getButtonElement(element);
117
+ const { alignment, ...buttonProps } = buttonElement.props;
118
+ return buttonProps;
119
+ }
120
+ getImageMetadata(element) {
121
+ const imageElement = this.getImageElement(element);
122
+ const props = imageElement.props;
123
+ return {
124
+ src: props.src,
125
+ alt: props.alt,
126
+ mode: props.rounded ? 'rounded' : 'box',
127
+ size: 'medium',
128
+ shaded: false,
129
+ bordered: false,
130
+ alignment: props.alignment || 'center',
131
+ caption: props.caption,
132
+ captionSize: 'medium',
133
+ width: props.maxWidth ? parseInt(props.maxWidth.replace('px', '')) : undefined,
134
+ };
135
+ }
136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ArticleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
137
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ArticleComponent, isStandalone: true, selector: "val-article", inputs: { props: "props" }, ngImport: i0, template: `
138
+ <article
139
+ class="val-article"
140
+ [class]="props.cssClass"
141
+ [ngClass]="{
142
+ 'val-article--centered': props.centered,
143
+ 'val-article--light': props.theme === 'light',
144
+ 'val-article--dark': props.theme === 'dark',
145
+ }"
146
+ [style.max-width]="props.maxWidth"
147
+ >
148
+ <div
149
+ *ngFor="let element of props.elements; trackBy: trackByFn"
150
+ class="val-article__element"
151
+ [class]="element.cssClass"
152
+ [ngClass]="getElementSpacingClass(element)"
153
+ [style.display]="element.visible === false ? 'none' : 'block'"
154
+ >
155
+ <!-- Título -->
156
+ <ng-container *ngIf="element.type === 'title'">
157
+ <val-title [props]="getTitleElement(element).props"></val-title>
158
+ </ng-container>
159
+
160
+ <!-- Subtítulo -->
161
+ <ng-container *ngIf="element.type === 'subtitle'">
162
+ <val-title [props]="getSubtitleElement(element).props"></val-title>
163
+ </ng-container>
164
+
165
+ <!-- Texto/Párrafo -->
166
+ <ng-container *ngIf="element.type === 'text' || element.type === 'paragraph'">
167
+ <val-text [props]="getTextElement(element).props"></val-text>
168
+ </ng-container>
169
+
170
+ <!-- Cita -->
171
+ <ng-container *ngIf="element.type === 'quote'">
172
+ <div class="val-article__quote">
173
+ <div class="val-article__quote-content">
174
+ <val-text [props]="getQuoteTextProps(element)"></val-text>
175
+ </div>
176
+ <div *ngIf="getQuoteElement(element).props.author" class="val-article__quote-author">
177
+ — {{ getQuoteElement(element).props.author }}
178
+ <span *ngIf="getQuoteElement(element).props.source" class="val-article__quote-source">
179
+ , {{ getQuoteElement(element).props.source }}
180
+ </span>
181
+ </div>
182
+ </div>
183
+ </ng-container>
184
+
185
+ <!-- Texto destacado -->
186
+ <ng-container *ngIf="element.type === 'highlight'">
187
+ <div
188
+ class="val-article__highlight"
189
+ [ngClass]="{
190
+ 'val-article__highlight--rounded': getHighlightElement(element).props.rounded,
191
+ }"
192
+ [style.background-color]="getHighlightColor(element)"
193
+ >
194
+ <val-text [props]="getHighlightTextProps(element)"></val-text>
195
+ </div>
196
+ </ng-container>
197
+
198
+ <!-- Código -->
199
+ <ng-container *ngIf="element.type === 'code'">
200
+ <div class="val-article__code">
201
+ <div *ngIf="getCodeElement(element).props.language" class="val-article__code-language">
202
+ {{ getCodeElement(element).props.language }}
203
+ </div>
204
+ <pre
205
+ class="val-article__code-content"
206
+ [ngClass]="{
207
+ 'val-article__code-content--dark': getCodeElement(element).props.theme === 'dark',
208
+ }"
209
+ ><code>{{ getCodeElement(element).props.code }}</code></pre>
210
+ </div>
211
+ </ng-container>
212
+
213
+ <!-- Lista -->
214
+ <ng-container *ngIf="element.type === 'list'">
215
+ <ul *ngIf="getListElement(element).props.listType !== 'ordered'" class="val-article__list">
216
+ <li *ngFor="let item of getListElement(element).props.items" class="val-article__list-item">
217
+ <span *ngIf="getListElement(element).props.listType === 'checklist'" class="val-article__list-check"
218
+ >✓</span
219
+ >
220
+ {{ item.text }}
221
+ </li>
222
+ </ul>
223
+ <ol
224
+ *ngIf="getListElement(element).props.listType === 'ordered'"
225
+ class="val-article__list val-article__list--ordered"
226
+ >
227
+ <li *ngFor="let item of getListElement(element).props.items" class="val-article__list-item">
228
+ {{ item.text }}
229
+ </li>
230
+ </ol>
231
+ </ng-container>
232
+
233
+ <!-- Botón -->
234
+ <ng-container *ngIf="element.type === 'button'">
235
+ <div
236
+ class="val-article__button-container"
237
+ [ngClass]="{
238
+ 'val-article__button-container--left': getButtonElement(element).props.alignment === 'left',
239
+ 'val-article__button-container--center': getButtonElement(element).props.alignment === 'center',
240
+ 'val-article__button-container--right': getButtonElement(element).props.alignment === 'right',
241
+ }"
242
+ >
243
+ <val-button [props]="getButtonProps(element)"></val-button>
244
+ </div>
245
+ </ng-container>
246
+
247
+ <!-- Separador -->
248
+ <ng-container *ngIf="element.type === 'separator'">
249
+ <div class="val-article__separator">
250
+ <hr
251
+ *ngIf="getSeparatorElement(element).props.style === 'line'"
252
+ class="val-article__separator-line"
253
+ [ngClass]="{
254
+ 'val-article__separator-line--thin': getSeparatorElement(element).props.thickness === 'thin',
255
+ 'val-article__separator-line--thick': getSeparatorElement(element).props.thickness === 'thick',
256
+ }"
257
+ />
258
+ <div *ngIf="getSeparatorElement(element).props.style === 'dots'" class="val-article__separator-dots">
259
+ • • •
260
+ </div>
261
+ <div
262
+ *ngIf="getSeparatorElement(element).props.style === 'space'"
263
+ class="val-article__separator-space"
264
+ ></div>
265
+ </div>
266
+ </ng-container>
267
+
268
+ <!-- Imagen -->
269
+ <ng-container *ngIf="element.type === 'image'">
270
+ <val-image [props]="getImageMetadata(element)"></val-image>
271
+ </ng-container>
272
+
273
+ <!-- Video -->
274
+ <ng-container *ngIf="element.type === 'video'">
275
+ <div class="val-article__video">
276
+ <video
277
+ [src]="getVideoElement(element).props.src"
278
+ [poster]="getVideoElement(element).props.poster"
279
+ [controls]="getVideoElement(element).props.controls !== false"
280
+ [autoplay]="getVideoElement(element).props.autoplay"
281
+ [muted]="getVideoElement(element).props.muted"
282
+ [style.max-width]="getVideoElement(element).props.maxWidth"
283
+ class="val-article__video-content"
284
+ >
285
+ Tu navegador no soporta el elemento video.
286
+ </video>
287
+ <div *ngIf="getVideoElement(element).props.title" class="val-article__video-title">
288
+ {{ getVideoElement(element).props.title }}
289
+ </div>
290
+ </div>
291
+ </ng-container>
292
+
293
+ <!-- Contenido personalizado -->
294
+ <ng-container *ngIf="element.type === 'custom'">
295
+ <div class="val-article__custom" [innerHTML]="getCustomElement(element).props.htmlContent"></div>
296
+ </ng-container>
297
+ </div>
298
+ </article>
299
+ `, isInline: true, styles: [".val-article{width:100%;margin:0 auto;line-height:1.6;color:var(--ion-color-dark, #1f2937);display:block;position:static}.val-article--centered{margin:0 auto}.val-article--light{background-color:var(--ion-color-light, #ffffff);color:var(--ion-color-dark, #1f2937)}.val-article--dark{background-color:var(--ion-color-dark, #1f2937);color:var(--ion-color-light, #ffffff)}.val-article__element{position:relative}.val-article__element:last-child{margin-bottom:0!important}.val-article__spacing-top--none{margin-top:0!important}.val-article__spacing-top--small{margin-top:.5rem!important}.val-article__spacing-top--medium{margin-top:1rem!important}.val-article__spacing-top--large{margin-top:1.5rem!important}.val-article__spacing-top--xlarge{margin-top:2.5rem!important}.val-article__spacing-bottom--none{margin-bottom:0!important}.val-article__spacing-bottom--small{margin-bottom:.5rem!important}.val-article__spacing-bottom--medium{margin-bottom:1rem!important}.val-article__spacing-bottom--large{margin-bottom:1.5rem!important}.val-article__spacing-bottom--xlarge{margin-bottom:2.5rem!important}.val-article__spacing-horizontal--none{margin-left:0!important;margin-right:0!important}.val-article__spacing-horizontal--small{margin-left:.5rem!important;margin-right:.5rem!important}.val-article__spacing-horizontal--medium{margin-left:1rem!important;margin-right:1rem!important}.val-article__spacing-horizontal--large{margin-left:1.5rem!important;margin-right:1.5rem!important}.val-article__spacing-horizontal--xlarge{margin-left:2.5rem!important;margin-right:2.5rem!important}.val-article__quote{border-left:4px solid #0969da;padding:1rem;margin:1rem 0;background-color:var(--ion-color-light-shade, #f8f9fa);border-radius:0 8px 8px 0;font-style:italic}.val-article__quote-content{margin-bottom:.5rem;font-size:1.1em}.val-article__quote-author{font-size:.9em;color:var(--ion-color-medium, #6c757d);font-style:normal;font-weight:500;text-align:right}.val-article__quote-source{font-weight:400;opacity:.8}.val-article__highlight{padding:1rem;margin:.5rem 0;background-color:var(--ion-color-warning-tint, #fff3cd);border:1px solid var(--ion-color-warning, #ffc107);border-radius:4px}.val-article__highlight--rounded{border-radius:12px}.val-article__code{margin:1rem 0;border-radius:8px;overflow:hidden;border:1px solid #e1e5e9}.val-article__code-language{background-color:var(--ion-color-medium-tint, #f8f9fa);padding:.5rem 1rem;font-size:.875em;font-weight:500;color:var(--ion-color-dark, #495057);border-bottom:1px solid #e1e5e9;text-transform:uppercase;letter-spacing:.5px}.val-article__code-content{background-color:#f6f8fa;color:#24292e;padding:1rem;margin:0;overflow-x:auto;font-family:SFMono-Regular,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875em;line-height:1.5}.val-article__code-content code{background:none;padding:0;font-size:inherit;color:inherit}.val-article__code-content--dark{background-color:#161b22;color:#f0f6fc}.val-article__list{margin:1rem 0;padding-left:1.5rem}.val-article__list--ordered{list-style-type:decimal}.val-article__list-item{margin-bottom:.5rem;line-height:1.6;position:relative}.val-article__list-item:last-child{margin-bottom:0}.val-article__list-check{color:var(--ion-color-success, #28a745);font-weight:700;margin-right:.5rem;position:absolute;left:-1.5rem}.val-article .val-article__list:has(.val-article__list-check){list-style:none;padding-left:1rem}.val-article__button-container{margin:1rem 0}.val-article__button-container--left{text-align:left}.val-article__button-container--center{text-align:center}.val-article__button-container--right{text-align:right}.val-article__separator{margin:1.5rem 0;text-align:center}.val-article__separator-line{border:none;height:1px;background-color:#d0d7de;margin:0}.val-article__separator-line--thin{height:1px}.val-article__separator-line--thick{height:3px}.val-article__separator-dots{color:#d0d7de;font-size:1.5em;letter-spacing:.5em;-webkit-user-select:none;user-select:none}.val-article__separator-space{height:1.5rem}.val-article__image{margin:1.5rem 0;text-align:center}.val-article__image--left{text-align:left}.val-article__image--center{text-align:center}.val-article__image--right{text-align:right}.val-article__image-content{max-width:100%;height:auto;border-radius:4px;box-shadow:0 2px 8px #0000001a;transition:transform .2s ease}.val-article__image-content:hover{transform:scale(1.02)}.val-article__image-content--rounded{border-radius:12px}.val-article__image-caption{margin-top:.5rem;font-size:.875em;color:var(--ion-color-medium, #6c757d);font-style:italic;text-align:center}.val-article__video{margin:1.5rem 0;text-align:center}.val-article__video-content{max-width:100%;height:auto;border-radius:8px;box-shadow:0 4px 12px #00000026}.val-article__video-title{margin-top:.5rem;font-size:.9em;color:var(--ion-color-medium, #6c757d);font-weight:500}.val-article__custom{margin:1rem 0}.val-article__custom *{max-width:100%}@media (max-width: 768px){.val-article__code-content{font-size:.8em;padding:.5rem}.val-article__image-content:hover{transform:none}.val-article__quote{padding:.5rem;margin:.5rem 0}.val-article__highlight{padding:.5rem}}@media (prefers-color-scheme: dark){.val-article--auto{background-color:var(--ion-color-dark, #1f2937);color:var(--ion-color-light, #ffffff)}.val-article--auto .val-article__quote{background-color:#ffffff0d}.val-article--auto .val-article__highlight{background-color:#ffc1071a;border-color:var(--ion-color-warning-shade, #e0a800)}.val-article--auto .val-article__code-content{background-color:#161b22;color:#f0f6fc}}.val-article__element{animation:fadeInUp .3s ease-out}@keyframes fadeInUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media (prefers-contrast: high){.val-article__separator-line{background-color:currentColor;opacity:.5}.val-article__quote{border-left-width:6px}}@media (prefers-reduced-motion: reduce){.val-article .val-article__element{animation:none}.val-article__image-content{transition:none}.val-article__image-content:hover{transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["props"], outputs: ["onClick"] }, { kind: "component", type: ImageComponent, selector: "val-image", inputs: ["props"] }] }); }
300
+ }
301
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ArticleComponent, decorators: [{
302
+ type: Component,
303
+ args: [{ selector: 'val-article', standalone: true, imports: [CommonModule, TitleComponent, TextComponent, ButtonComponent, ImageComponent], template: `
304
+ <article
305
+ class="val-article"
306
+ [class]="props.cssClass"
307
+ [ngClass]="{
308
+ 'val-article--centered': props.centered,
309
+ 'val-article--light': props.theme === 'light',
310
+ 'val-article--dark': props.theme === 'dark',
311
+ }"
312
+ [style.max-width]="props.maxWidth"
313
+ >
314
+ <div
315
+ *ngFor="let element of props.elements; trackBy: trackByFn"
316
+ class="val-article__element"
317
+ [class]="element.cssClass"
318
+ [ngClass]="getElementSpacingClass(element)"
319
+ [style.display]="element.visible === false ? 'none' : 'block'"
320
+ >
321
+ <!-- Título -->
322
+ <ng-container *ngIf="element.type === 'title'">
323
+ <val-title [props]="getTitleElement(element).props"></val-title>
324
+ </ng-container>
325
+
326
+ <!-- Subtítulo -->
327
+ <ng-container *ngIf="element.type === 'subtitle'">
328
+ <val-title [props]="getSubtitleElement(element).props"></val-title>
329
+ </ng-container>
330
+
331
+ <!-- Texto/Párrafo -->
332
+ <ng-container *ngIf="element.type === 'text' || element.type === 'paragraph'">
333
+ <val-text [props]="getTextElement(element).props"></val-text>
334
+ </ng-container>
335
+
336
+ <!-- Cita -->
337
+ <ng-container *ngIf="element.type === 'quote'">
338
+ <div class="val-article__quote">
339
+ <div class="val-article__quote-content">
340
+ <val-text [props]="getQuoteTextProps(element)"></val-text>
341
+ </div>
342
+ <div *ngIf="getQuoteElement(element).props.author" class="val-article__quote-author">
343
+ — {{ getQuoteElement(element).props.author }}
344
+ <span *ngIf="getQuoteElement(element).props.source" class="val-article__quote-source">
345
+ , {{ getQuoteElement(element).props.source }}
346
+ </span>
347
+ </div>
348
+ </div>
349
+ </ng-container>
350
+
351
+ <!-- Texto destacado -->
352
+ <ng-container *ngIf="element.type === 'highlight'">
353
+ <div
354
+ class="val-article__highlight"
355
+ [ngClass]="{
356
+ 'val-article__highlight--rounded': getHighlightElement(element).props.rounded,
357
+ }"
358
+ [style.background-color]="getHighlightColor(element)"
359
+ >
360
+ <val-text [props]="getHighlightTextProps(element)"></val-text>
361
+ </div>
362
+ </ng-container>
363
+
364
+ <!-- Código -->
365
+ <ng-container *ngIf="element.type === 'code'">
366
+ <div class="val-article__code">
367
+ <div *ngIf="getCodeElement(element).props.language" class="val-article__code-language">
368
+ {{ getCodeElement(element).props.language }}
369
+ </div>
370
+ <pre
371
+ class="val-article__code-content"
372
+ [ngClass]="{
373
+ 'val-article__code-content--dark': getCodeElement(element).props.theme === 'dark',
374
+ }"
375
+ ><code>{{ getCodeElement(element).props.code }}</code></pre>
376
+ </div>
377
+ </ng-container>
378
+
379
+ <!-- Lista -->
380
+ <ng-container *ngIf="element.type === 'list'">
381
+ <ul *ngIf="getListElement(element).props.listType !== 'ordered'" class="val-article__list">
382
+ <li *ngFor="let item of getListElement(element).props.items" class="val-article__list-item">
383
+ <span *ngIf="getListElement(element).props.listType === 'checklist'" class="val-article__list-check"
384
+ >✓</span
385
+ >
386
+ {{ item.text }}
387
+ </li>
388
+ </ul>
389
+ <ol
390
+ *ngIf="getListElement(element).props.listType === 'ordered'"
391
+ class="val-article__list val-article__list--ordered"
392
+ >
393
+ <li *ngFor="let item of getListElement(element).props.items" class="val-article__list-item">
394
+ {{ item.text }}
395
+ </li>
396
+ </ol>
397
+ </ng-container>
398
+
399
+ <!-- Botón -->
400
+ <ng-container *ngIf="element.type === 'button'">
401
+ <div
402
+ class="val-article__button-container"
403
+ [ngClass]="{
404
+ 'val-article__button-container--left': getButtonElement(element).props.alignment === 'left',
405
+ 'val-article__button-container--center': getButtonElement(element).props.alignment === 'center',
406
+ 'val-article__button-container--right': getButtonElement(element).props.alignment === 'right',
407
+ }"
408
+ >
409
+ <val-button [props]="getButtonProps(element)"></val-button>
410
+ </div>
411
+ </ng-container>
412
+
413
+ <!-- Separador -->
414
+ <ng-container *ngIf="element.type === 'separator'">
415
+ <div class="val-article__separator">
416
+ <hr
417
+ *ngIf="getSeparatorElement(element).props.style === 'line'"
418
+ class="val-article__separator-line"
419
+ [ngClass]="{
420
+ 'val-article__separator-line--thin': getSeparatorElement(element).props.thickness === 'thin',
421
+ 'val-article__separator-line--thick': getSeparatorElement(element).props.thickness === 'thick',
422
+ }"
423
+ />
424
+ <div *ngIf="getSeparatorElement(element).props.style === 'dots'" class="val-article__separator-dots">
425
+ • • •
426
+ </div>
427
+ <div
428
+ *ngIf="getSeparatorElement(element).props.style === 'space'"
429
+ class="val-article__separator-space"
430
+ ></div>
431
+ </div>
432
+ </ng-container>
433
+
434
+ <!-- Imagen -->
435
+ <ng-container *ngIf="element.type === 'image'">
436
+ <val-image [props]="getImageMetadata(element)"></val-image>
437
+ </ng-container>
438
+
439
+ <!-- Video -->
440
+ <ng-container *ngIf="element.type === 'video'">
441
+ <div class="val-article__video">
442
+ <video
443
+ [src]="getVideoElement(element).props.src"
444
+ [poster]="getVideoElement(element).props.poster"
445
+ [controls]="getVideoElement(element).props.controls !== false"
446
+ [autoplay]="getVideoElement(element).props.autoplay"
447
+ [muted]="getVideoElement(element).props.muted"
448
+ [style.max-width]="getVideoElement(element).props.maxWidth"
449
+ class="val-article__video-content"
450
+ >
451
+ Tu navegador no soporta el elemento video.
452
+ </video>
453
+ <div *ngIf="getVideoElement(element).props.title" class="val-article__video-title">
454
+ {{ getVideoElement(element).props.title }}
455
+ </div>
456
+ </div>
457
+ </ng-container>
458
+
459
+ <!-- Contenido personalizado -->
460
+ <ng-container *ngIf="element.type === 'custom'">
461
+ <div class="val-article__custom" [innerHTML]="getCustomElement(element).props.htmlContent"></div>
462
+ </ng-container>
463
+ </div>
464
+ </article>
465
+ `, styles: [".val-article{width:100%;margin:0 auto;line-height:1.6;color:var(--ion-color-dark, #1f2937);display:block;position:static}.val-article--centered{margin:0 auto}.val-article--light{background-color:var(--ion-color-light, #ffffff);color:var(--ion-color-dark, #1f2937)}.val-article--dark{background-color:var(--ion-color-dark, #1f2937);color:var(--ion-color-light, #ffffff)}.val-article__element{position:relative}.val-article__element:last-child{margin-bottom:0!important}.val-article__spacing-top--none{margin-top:0!important}.val-article__spacing-top--small{margin-top:.5rem!important}.val-article__spacing-top--medium{margin-top:1rem!important}.val-article__spacing-top--large{margin-top:1.5rem!important}.val-article__spacing-top--xlarge{margin-top:2.5rem!important}.val-article__spacing-bottom--none{margin-bottom:0!important}.val-article__spacing-bottom--small{margin-bottom:.5rem!important}.val-article__spacing-bottom--medium{margin-bottom:1rem!important}.val-article__spacing-bottom--large{margin-bottom:1.5rem!important}.val-article__spacing-bottom--xlarge{margin-bottom:2.5rem!important}.val-article__spacing-horizontal--none{margin-left:0!important;margin-right:0!important}.val-article__spacing-horizontal--small{margin-left:.5rem!important;margin-right:.5rem!important}.val-article__spacing-horizontal--medium{margin-left:1rem!important;margin-right:1rem!important}.val-article__spacing-horizontal--large{margin-left:1.5rem!important;margin-right:1.5rem!important}.val-article__spacing-horizontal--xlarge{margin-left:2.5rem!important;margin-right:2.5rem!important}.val-article__quote{border-left:4px solid #0969da;padding:1rem;margin:1rem 0;background-color:var(--ion-color-light-shade, #f8f9fa);border-radius:0 8px 8px 0;font-style:italic}.val-article__quote-content{margin-bottom:.5rem;font-size:1.1em}.val-article__quote-author{font-size:.9em;color:var(--ion-color-medium, #6c757d);font-style:normal;font-weight:500;text-align:right}.val-article__quote-source{font-weight:400;opacity:.8}.val-article__highlight{padding:1rem;margin:.5rem 0;background-color:var(--ion-color-warning-tint, #fff3cd);border:1px solid var(--ion-color-warning, #ffc107);border-radius:4px}.val-article__highlight--rounded{border-radius:12px}.val-article__code{margin:1rem 0;border-radius:8px;overflow:hidden;border:1px solid #e1e5e9}.val-article__code-language{background-color:var(--ion-color-medium-tint, #f8f9fa);padding:.5rem 1rem;font-size:.875em;font-weight:500;color:var(--ion-color-dark, #495057);border-bottom:1px solid #e1e5e9;text-transform:uppercase;letter-spacing:.5px}.val-article__code-content{background-color:#f6f8fa;color:#24292e;padding:1rem;margin:0;overflow-x:auto;font-family:SFMono-Regular,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875em;line-height:1.5}.val-article__code-content code{background:none;padding:0;font-size:inherit;color:inherit}.val-article__code-content--dark{background-color:#161b22;color:#f0f6fc}.val-article__list{margin:1rem 0;padding-left:1.5rem}.val-article__list--ordered{list-style-type:decimal}.val-article__list-item{margin-bottom:.5rem;line-height:1.6;position:relative}.val-article__list-item:last-child{margin-bottom:0}.val-article__list-check{color:var(--ion-color-success, #28a745);font-weight:700;margin-right:.5rem;position:absolute;left:-1.5rem}.val-article .val-article__list:has(.val-article__list-check){list-style:none;padding-left:1rem}.val-article__button-container{margin:1rem 0}.val-article__button-container--left{text-align:left}.val-article__button-container--center{text-align:center}.val-article__button-container--right{text-align:right}.val-article__separator{margin:1.5rem 0;text-align:center}.val-article__separator-line{border:none;height:1px;background-color:#d0d7de;margin:0}.val-article__separator-line--thin{height:1px}.val-article__separator-line--thick{height:3px}.val-article__separator-dots{color:#d0d7de;font-size:1.5em;letter-spacing:.5em;-webkit-user-select:none;user-select:none}.val-article__separator-space{height:1.5rem}.val-article__image{margin:1.5rem 0;text-align:center}.val-article__image--left{text-align:left}.val-article__image--center{text-align:center}.val-article__image--right{text-align:right}.val-article__image-content{max-width:100%;height:auto;border-radius:4px;box-shadow:0 2px 8px #0000001a;transition:transform .2s ease}.val-article__image-content:hover{transform:scale(1.02)}.val-article__image-content--rounded{border-radius:12px}.val-article__image-caption{margin-top:.5rem;font-size:.875em;color:var(--ion-color-medium, #6c757d);font-style:italic;text-align:center}.val-article__video{margin:1.5rem 0;text-align:center}.val-article__video-content{max-width:100%;height:auto;border-radius:8px;box-shadow:0 4px 12px #00000026}.val-article__video-title{margin-top:.5rem;font-size:.9em;color:var(--ion-color-medium, #6c757d);font-weight:500}.val-article__custom{margin:1rem 0}.val-article__custom *{max-width:100%}@media (max-width: 768px){.val-article__code-content{font-size:.8em;padding:.5rem}.val-article__image-content:hover{transform:none}.val-article__quote{padding:.5rem;margin:.5rem 0}.val-article__highlight{padding:.5rem}}@media (prefers-color-scheme: dark){.val-article--auto{background-color:var(--ion-color-dark, #1f2937);color:var(--ion-color-light, #ffffff)}.val-article--auto .val-article__quote{background-color:#ffffff0d}.val-article--auto .val-article__highlight{background-color:#ffc1071a;border-color:var(--ion-color-warning-shade, #e0a800)}.val-article--auto .val-article__code-content{background-color:#161b22;color:#f0f6fc}}.val-article__element{animation:fadeInUp .3s ease-out}@keyframes fadeInUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media (prefers-contrast: high){.val-article__separator-line{background-color:currentColor;opacity:.5}.val-article__quote{border-left-width:6px}}@media (prefers-reduced-motion: reduce){.val-article .val-article__element{animation:none}.val-article__image-content{transition:none}.val-article__image-content:hover{transform:none}}\n"] }]
466
+ }], ctorParameters: () => [], propDecorators: { props: [{
467
+ type: Input
468
+ }] } });
469
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJ0aWNsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0ZWNoLWNvbXBvbmVudHMvc3JjL2xpYi9jb21wb25lbnRzL29yZ2FuaXNtcy9hcnRpY2xlL2FydGljbGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7OztBQTRMbkU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBUTNCLGdCQUFlLENBQUM7SUFFaEIsUUFBUTtRQUNOLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDeEMsT0FBTyxDQUFDLElBQUksQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO1FBQzFELENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLENBQUMsS0FBYSxFQUFFLE9BQXVCO1FBQzlDLE9BQU8sT0FBTyxDQUFDLEVBQUUsSUFBSSxLQUFLLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsc0JBQXNCLENBQUMsT0FBdUI7UUFDNUMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMs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WSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLGNBQWMsQ0FBQyxZQUM3RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0tUO3dEQWlDRCxLQUFLO3NCQURKLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9idXR0b24vYnV0dG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJbWFnZUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL2ltYWdlL2ltYWdlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJbWFnZU1ldGFkYXRhIH0gZnJvbSAnLi4vLi4vYXRvbXMvaW1hZ2UvdHlwZXMnO1xuaW1wb3J0IHsgVGV4dENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL3RleHQvdGV4dC5jb21wb25lbnQnO1xuaW1wb3J0IHsgVGl0bGVDb21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy90aXRsZS90aXRsZS5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgQXJ0aWNsZUJ1dHRvbkVsZW1lbnQsXG4gIEFydGljbGVDb2RlRWxlbWVudCxcbiAgQXJ0aWNsZUN1c3RvbUVsZW1lbnQsXG4gIEFydGljbGVFbGVtZW50LFxuICBBcnRpY2xlSGlnaGxpZ2h0RWxlbWVudCxcbiAgQXJ0aWNsZUltYWdlRWxlbWVudCxcbiAgQXJ0aWNsZUxpc3RFbGVtZW50LFxuICBBcnRpY2xlTWV0YWRhdGEsXG4gIEFydGljbGVRdW90ZUVsZW1lbnQsXG4gIEFydGljbGVTZXBhcmF0b3JFbGVtZW50LFxuICBBcnRpY2xlU3VidGl0bGVFbGVtZW50LFxuICBBcnRpY2xlVGV4dEVsZW1lbnQsXG4gIEFydGljbGVUaXRsZUVsZW1lbnQsXG4gIEFydGljbGVWaWRlb0VsZW1lbnQsXG59IGZyb20gJy4vdHlwZXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtYXJ0aWNsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFRpdGxlQ29tcG9uZW50LCBUZXh0Q29tcG9uZW50LCBCdXR0b25Db21wb25lbnQsIEltYWdlQ29tcG9uZW50XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8YXJ0aWNsZVxuICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZVwiXG4gICAgICBbY2xhc3NdPVwicHJvcHMuY3NzQ2xhc3NcIlxuICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAndmFsLWFydGljbGUtLWNlbnRlcmVkJzogcHJvcHMuY2VudGVyZWQsXG4gICAgICAgICd2YWwtYXJ0aWNsZS0tbGlnaHQnOiBwcm9wcy50aGVtZSA9PT0gJ2xpZ2h0JyxcbiAgICAgICAgJ3ZhbC1hcnRpY2xlLS1kYXJrJzogcHJvcHMudGhlbWUgPT09ICdkYXJrJyxcbiAgICAgIH1cIlxuICAgICAgW3N0eWxlLm1heC13aWR0aF09XCJwcm9wcy5tYXhXaWR0aFwiXG4gICAgPlxuICAgICAgPGRpdlxuICAgICAgICAqbmdGb3I9XCJsZXQgZWxlbWVudCBvZiBwcm9wcy5lbGVtZW50czsgdHJhY2tCeTogdHJhY2tCeUZuXCJcbiAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fZWxlbWVudFwiXG4gICAgICAgIFtjbGFzc109XCJlbGVtZW50LmNzc0NsYXNzXCJcbiAgICAgICAgW25nQ2xhc3NdPVwiZ2V0RWxlbWVudFNwYWNpbmdDbGFzcyhlbGVtZW50KVwiXG4gICAgICAgIFtzdHlsZS5kaXNwbGF5XT1cImVsZW1lbnQudmlzaWJsZSA9PT0gZmFsc2UgPyAnbm9uZScgOiAnYmxvY2snXCJcbiAgICAgID5cbiAgICAgICAgPCEtLSBUw610dWxvIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZWxlbWVudC50eXBlID09PSAndGl0bGUnXCI+XG4gICAgICAgICAgPHZhbC10aXRsZSBbcHJvcHNdPVwiZ2V0VGl0bGVFbGVtZW50KGVsZW1lbnQpLnByb3BzXCI+PC92YWwtdGl0bGU+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gU3VidMOtdHVsbyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVsZW1lbnQudHlwZSA9PT0gJ3N1YnRpdGxlJ1wiPlxuICAgICAgICAgIDx2YWwtdGl0bGUgW3Byb3BzXT1cImdldFN1YnRpdGxlRWxlbWVudChlbGVtZW50KS5wcm9wc1wiPjwvdmFsLXRpdGxlPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIFRleHRvL1DDoXJyYWZvIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZWxlbWVudC50eXBlID09PSAndGV4dCcgfHwgZWxlbWVudC50eXBlID09PSAncGFyYWdyYXBoJ1wiPlxuICAgICAgICAgIDx2YWwtdGV4dCBbcHJvcHNdPVwiZ2V0VGV4dEVsZW1lbnQoZWxlbWVudCkucHJvcHNcIj48L3ZhbC10ZXh0PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIENpdGEgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbGVtZW50LnR5cGUgPT09ICdxdW90ZSdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsLWFydGljbGVfX3F1b3RlXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsLWFydGljbGVfX3F1b3RlLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgPHZhbC10ZXh0IFtwcm9wc109XCJnZXRRdW90ZVRleHRQcm9wcyhlbGVtZW50KVwiPjwvdmFsLXRleHQ+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJnZXRRdW90ZUVsZW1lbnQoZWxlbWVudCkucHJvcHMuYXV0aG9yXCIgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fcXVvdGUtYXV0aG9yXCI+XG4gICAgICAgICAgICAgIOKAlCB7eyBnZXRRdW90ZUVsZW1lbnQoZWxlbWVudCkucHJvcHMuYXV0aG9yIH19XG4gICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiZ2V0UXVvdGVFbGVtZW50KGVsZW1lbnQpLnByb3BzLnNvdXJjZVwiIGNsYXNzPVwidmFsLWFydGljbGVfX3F1b3RlLXNvdXJjZVwiPlxuICAgICAgICAgICAgICAgICwge3sgZ2V0UXVvdGVFbGVtZW50KGVsZW1lbnQpLnByb3BzLnNvdXJjZSB9fVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBUZXh0byBkZXN0YWNhZG8gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbGVtZW50LnR5cGUgPT09ICdoaWdobGlnaHQnXCI+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9faGlnaGxpZ2h0XCJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAgICAgJ3ZhbC1hcnRpY2xlX19oaWdobGlnaHQtLXJvdW5kZWQnOiBnZXRIaWdobGlnaHRFbGVtZW50KGVsZW1lbnQpLnByb3BzLnJvdW5kZWQsXG4gICAgICAgICAgICB9XCJcbiAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kLWNvbG9yXT1cImdldEhpZ2hsaWdodENvbG9yKGVsZW1lbnQpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8dmFsLXRleHQgW3Byb3BzXT1cImdldEhpZ2hsaWdodFRleHRQcm9wcyhlbGVtZW50KVwiPjwvdmFsLXRleHQ+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gQ8OzZGlnbyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVsZW1lbnQudHlwZSA9PT0gJ2NvZGUnXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInZhbC1hcnRpY2xlX19jb2RlXCI+XG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZ2V0Q29kZUVsZW1lbnQoZWxlbWVudCkucHJvcHMubGFuZ3VhZ2VcIiBjbGFzcz1cInZhbC1hcnRpY2xlX19jb2RlLWxhbmd1YWdlXCI+XG4gICAgICAgICAgICAgIHt7IGdldENvZGVFbGVtZW50KGVsZW1lbnQpLnByb3BzLmxhbmd1YWdlIH19XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxwcmVcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fY29kZS1jb250ZW50XCJcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICAgICAgICd2YWwtYXJ0aWNsZV9fY29kZS1jb250ZW50LS1kYXJrJzogZ2V0Q29kZUVsZW1lbnQoZWxlbWVudCkucHJvcHMudGhlbWUgPT09ICdkYXJrJyxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICA+PGNvZGU+e3sgZ2V0Q29kZUVsZW1lbnQoZWxlbWVudCkucHJvcHMuY29kZSB9fTwvY29kZT48L3ByZT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBMaXN0YSAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVsZW1lbnQudHlwZSA9PT0gJ2xpc3QnXCI+XG4gICAgICAgICAgPHVsICpuZ0lmPVwiZ2V0TGlzdEVsZW1lbnQoZWxlbWVudCkucHJvcHMubGlzdFR5cGUgIT09ICdvcmRlcmVkJ1wiIGNsYXNzPVwidmFsLWFydGljbGVfX2xpc3RcIj5cbiAgICAgICAgICAgIDxsaSAqbmdGb3I9XCJsZXQgaXRlbSBvZiBnZXRMaXN0RWxlbWVudChlbGVtZW50KS5wcm9wcy5pdGVtc1wiIGNsYXNzPVwidmFsLWFydGljbGVfX2xpc3QtaXRlbVwiPlxuICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImdldExpc3RFbGVtZW50KGVsZW1lbnQpLnByb3BzLmxpc3RUeXBlID09PSAnY2hlY2tsaXN0J1wiIGNsYXNzPVwidmFsLWFydGljbGVfX2xpc3QtY2hlY2tcIlxuICAgICAgICAgICAgICAgID7inJM8L3NwYW5cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBpdGVtLnRleHQgfX1cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPC91bD5cbiAgICAgICAgICA8b2xcbiAgICAgICAgICAgICpuZ0lmPVwiZ2V0TGlzdEVsZW1lbnQoZWxlbWVudCkucHJvcHMubGlzdFR5cGUgPT09ICdvcmRlcmVkJ1wiXG4gICAgICAgICAgICBjbGFzcz1cInZhbC1hcnRpY2xlX19saXN0IHZhbC1hcnRpY2xlX19saXN0LS1vcmRlcmVkXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bGkgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZ2V0TGlzdEVsZW1lbnQoZWxlbWVudCkucHJvcHMuaXRlbXNcIiBjbGFzcz1cInZhbC1hcnRpY2xlX19saXN0LWl0ZW1cIj5cbiAgICAgICAgICAgICAge3sgaXRlbS50ZXh0IH19XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgIDwvb2w+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gQm90w7NuIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZWxlbWVudC50eXBlID09PSAnYnV0dG9uJ1wiPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwidmFsLWFydGljbGVfX2J1dHRvbi1jb250YWluZXJcIlxuICAgICAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICAgICAndmFsLWFydGljbGVfX2J1dHRvbi1jb250YWluZXItLWxlZnQnOiBnZXRCdXR0b25FbGVtZW50KGVsZW1lbnQpLnByb3BzLmFsaWdubWVudCA9PT0gJ2xlZnQnLFxuICAgICAgICAgICAgICAndmFsLWFydGljbGVfX2J1dHRvbi1jb250YWluZXItLWNlbnRlcic6IGdldEJ1dHRvbkVsZW1lbnQoZWxlbWVudCkucHJvcHMuYWxpZ25tZW50ID09PSAnY2VudGVyJyxcbiAgICAgICAgICAgICAgJ3ZhbC1hcnRpY2xlX19idXR0b24tY29udGFpbmVyLS1yaWdodCc6IGdldEJ1dHRvbkVsZW1lbnQoZWxlbWVudCkucHJvcHMuYWxpZ25tZW50ID09PSAncmlnaHQnLFxuICAgICAgICAgICAgfVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHZhbC1idXR0b24gW3Byb3BzXT1cImdldEJ1dHRvblByb3BzKGVsZW1lbnQpXCI+PC92YWwtYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIFNlcGFyYWRvciAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVsZW1lbnQudHlwZSA9PT0gJ3NlcGFyYXRvcidcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsLWFydGljbGVfX3NlcGFyYXRvclwiPlxuICAgICAgICAgICAgPGhyXG4gICAgICAgICAgICAgICpuZ0lmPVwiZ2V0U2VwYXJhdG9yRWxlbWVudChlbGVtZW50KS5wcm9wcy5zdHlsZSA9PT0gJ2xpbmUnXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fc2VwYXJhdG9yLWxpbmVcIlxuICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAgICAgJ3ZhbC1hcnRpY2xlX19zZXBhcmF0b3ItbGluZS0tdGhpbic6IGdldFNlcGFyYXRvckVsZW1lbnQoZWxlbWVudCkucHJvcHMudGhpY2tuZXNzID09PSAndGhpbicsXG4gICAgICAgICAgICAgICAgJ3ZhbC1hcnRpY2xlX19zZXBhcmF0b3ItbGluZS0tdGhpY2snOiBnZXRTZXBhcmF0b3JFbGVtZW50KGVsZW1lbnQpLnByb3BzLnRoaWNrbmVzcyA9PT0gJ3RoaWNrJyxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cImdldFNlcGFyYXRvckVsZW1lbnQoZWxlbWVudCkucHJvcHMuc3R5bGUgPT09ICdkb3RzJ1wiIGNsYXNzPVwidmFsLWFydGljbGVfX3NlcGFyYXRvci1kb3RzXCI+XG4gICAgICAgICAgICAgIOKAoiDigKIg4oCiXG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgKm5nSWY9XCJnZXRTZXBhcmF0b3JFbGVtZW50KGVsZW1lbnQpLnByb3BzLnN0eWxlID09PSAnc3BhY2UnXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fc2VwYXJhdG9yLXNwYWNlXCJcbiAgICAgICAgICAgID48L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBJbWFnZW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbGVtZW50LnR5cGUgPT09ICdpbWFnZSdcIj5cbiAgICAgICAgICA8dmFsLWltYWdlIFtwcm9wc109XCJnZXRJbWFnZU1ldGFkYXRhKGVsZW1lbnQpXCI+PC92YWwtaW1hZ2U+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gVmlkZW8gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbGVtZW50LnR5cGUgPT09ICd2aWRlbydcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidmFsLWFydGljbGVfX3ZpZGVvXCI+XG4gICAgICAgICAgICA8dmlkZW9cbiAgICAgICAgICAgICAgW3NyY109XCJnZXRWaWRlb0VsZW1lbnQoZWxlbWVudCkucHJvcHMuc3JjXCJcbiAgICAgICAgICAgICAgW3Bvc3Rlcl09XCJnZXRWaWRlb0VsZW1lbnQoZWxlbWVudCkucHJvcHMucG9zdGVyXCJcbiAgICAgICAgICAgICAgW2NvbnRyb2xzXT1cImdldFZpZGVvRWxlbWVudChlbGVtZW50KS5wcm9wcy5jb250cm9scyAhPT0gZmFsc2VcIlxuICAgICAgICAgICAgICBbYXV0b3BsYXldPVwiZ2V0VmlkZW9FbGVtZW50KGVsZW1lbnQpLnByb3BzLmF1dG9wbGF5XCJcbiAgICAgICAgICAgICAgW211dGVkXT1cImdldFZpZGVvRWxlbWVudChlbGVtZW50KS5wcm9wcy5tdXRlZFwiXG4gICAgICAgICAgICAgIFtzdHlsZS5tYXgtd2lkdGhdPVwiZ2V0VmlkZW9FbGVtZW50KGVsZW1lbnQpLnByb3BzLm1heFdpZHRoXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fdmlkZW8tY29udGVudFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIFR1IG5hdmVnYWRvciBubyBzb3BvcnRhIGVsIGVsZW1lbnRvIHZpZGVvLlxuICAgICAgICAgICAgPC92aWRlbz5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJnZXRWaWRlb0VsZW1lbnQoZWxlbWVudCkucHJvcHMudGl0bGVcIiBjbGFzcz1cInZhbC1hcnRpY2xlX192aWRlby10aXRsZVwiPlxuICAgICAgICAgICAgICB7eyBnZXRWaWRlb0VsZW1lbnQoZWxlbWVudCkucHJvcHMudGl0bGUgfX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIENvbnRlbmlkbyBwZXJzb25hbGl6YWRvIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZWxlbWVudC50eXBlID09PSAnY3VzdG9tJ1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ2YWwtYXJ0aWNsZV9fY3VzdG9tXCIgW2lubmVySFRNTF09XCJnZXRDdXN0b21FbGVtZW50KGVsZW1lbnQpLnByb3BzLmh0bWxDb250ZW50XCI+PC9kaXY+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgPC9hcnRpY2xlPlxuICBgLFxuICBzdHlsZVVybHM6IFsnLi9hcnRpY2xlLmNvbXBvbmVudC5zY3NzJ10sXG4gIC8vIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLCAvLyBDb21lbnRhZG8gdGVtcG9yYWxtZW50ZSBwYXJhIGRlYnVnXG59KVxuLyoqXG4gKiB2YWwtYXJ0aWNsZVxuICpcbiAqIENvbXBvbmVudGUgcGFyYSBjcmVhciBhcnTDrWN1bG9zLCBibG9ncyB5IGRvY3VtZW50YWNpw7NuIGRlIGZvcm1hIGRlY2xhcmF0aXZhLlxuICogUGVybWl0ZSBjb21iaW5hciBtw7psdGlwbGVzIGVsZW1lbnRvcyAodMOtdHVsb3MsIHRleHRvLCBpbcOhZ2VuZXMsIGPDs2RpZ28sIGV0Yy4pXG4gKiBjb24gZXNwYWNpYWRvIGF1dG9tw6F0aWNvIHkgc29wb3J0ZSBtdWx0aS1pZGlvbWEuXG4gKlxuICogQGV4YW1wbGUgVXNvIGLDoXNpY286XG4gKiBgYGBodG1sXG4gKiA8dmFsLWFydGljbGUgW3Byb3BzXT1cImFydGljbGVDb25maWdcIj48L3ZhbC1hcnRpY2xlPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGUgQ29uIEFydGljbGVCdWlsZGVyOlxuICogYGBgdHlwZXNjcmlwdFxuICogYXJ0aWNsZUNvbmZpZyA9IG5ldyBBcnRpY2xlQnVpbGRlcigpXG4gKiAgIC50aXRsZSh0aXRsZVByb3BzKVxuICogICAucGFyYWdyYXBoKHRleHRQcm9wcylcbiAqICAgLmNvZGUoJ2NvbnNvbGUubG9nKFwiSGVsbG8gV29ybGRcIiknLCAnamF2YXNjcmlwdCcpXG4gKiAgIC5idWlsZCgpO1xuICogYGBgXG4gKlxuICogQGlucHV0IHByb3BzOiBBcnRpY2xlTWV0YWRhdGEgLSBDb25maWd1cmFjacOzbiBjb21wbGV0YSBkZWwgYXJ0w61jdWxvXG4gKi9cbmV4cG9ydCBjbGFzcyBBcnRpY2xlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYWNpw7NuIGRlbCBhcnTDrWN1bG9cbiAgICogQHR5cGUge0FydGljbGVNZXRhZGF0YX1cbiAgICovXG4gIEBJbnB1dCgpXG4gIHByb3BzITogQXJ0aWNsZU1ldGFkYXRhO1xuXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICAvLyBWYWxpZGFjacOzbiBiw6FzaWNhXG4gICAgaWYgKCF0aGlzLnByb3BzIHx8ICF0aGlzLnByb3BzLmVsZW1lbnRzKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ3ZhbC1hcnRpY2xlOiBwcm9wcy5lbGVtZW50cyBpcyByZXF1aXJlZCcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGdW5jacOzbiBkZSB0cmFja0J5IHBhcmEgb3B0aW1pemFyIGVsIHJlbmRlcmluZyBkZSBlbGVtZW50b3NcbiAgICovXG4gIHRyYWNrQnlGbihpbmRleDogbnVtYmVyLCBlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IGFueSB7XG4gICAgcmV0dXJuIGVsZW1lbnQuaWQgfHwgaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBsYXMgY2xhc2VzIENTUyBwYXJhIGVsIGVzcGFjaWFkbyBkZWwgZWxlbWVudG9cbiAgICovXG4gIGdldEVsZW1lbnRTcGFjaW5nQ2xhc3MoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IHNwYWNpbmcgPSBlbGVtZW50LnNwYWNpbmcgfHwgdGhpcy5wcm9wcy5kZWZhdWx0U3BhY2luZztcbiAgICBjb25zdCBjbGFzc2VzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKHNwYWNpbmc/LnRvcCkge1xuICAgICAgY2xhc3Nlcy5wdXNoKGB2YWwtYXJ0aWNsZV9fc3BhY2luZy10b3AtLSR7c3BhY2luZy50b3B9YCk7XG4gICAgfVxuICAgIGlmIChzcGFjaW5nPy5ib3R0b20pIHtcbiAgICAgIGNsYXNzZXMucHVzaChgdmFsLWFydGljbGVfX3NwYWNpbmctYm90dG9tLS0ke3NwYWNpbmcuYm90dG9tfWApO1xuICAgIH1cbiAgICBpZiAoc3BhY2luZz8uaG9yaXpvbnRhbCkge1xuICAgICAgY2xhc3Nlcy5wdXNoKGB2YWwtYXJ0aWNsZV9fc3BhY2luZy1ob3Jpem9udGFsLS0ke3NwYWNpbmcuaG9yaXpvbnRhbH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xhc3Nlcy5qb2luKCcgJyk7XG4gIH1cblxuICAvLyA9PT0gRlVOQ0lPTkVTIERFIFRJUE8gUEFSQSBUWVBFU0NSSVBUID09PVxuXG4gIGdldFRpdGxlRWxlbWVudChlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEFydGljbGVUaXRsZUVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVUaXRsZUVsZW1lbnQ7XG4gIH1cblxuICBnZXRTdWJ0aXRsZUVsZW1lbnQoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBBcnRpY2xlU3VidGl0bGVFbGVtZW50IHtcbiAgICByZXR1cm4gZWxlbWVudCBhcyBBcnRpY2xlU3VidGl0bGVFbGVtZW50O1xuICB9XG5cbiAgZ2V0VGV4dEVsZW1lbnQoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBBcnRpY2xlVGV4dEVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVUZXh0RWxlbWVudDtcbiAgfVxuXG4gIGdldFF1b3RlRWxlbWVudChlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEFydGljbGVRdW90ZUVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVRdW90ZUVsZW1lbnQ7XG4gIH1cblxuICBnZXRIaWdobGlnaHRFbGVtZW50KGVsZW1lbnQ6IEFydGljbGVFbGVtZW50KTogQXJ0aWNsZUhpZ2hsaWdodEVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVIaWdobGlnaHRFbGVtZW50O1xuICB9XG5cbiAgZ2V0Q29kZUVsZW1lbnQoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBBcnRpY2xlQ29kZUVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVDb2RlRWxlbWVudDtcbiAgfVxuXG4gIGdldExpc3RFbGVtZW50KGVsZW1lbnQ6IEFydGljbGVFbGVtZW50KTogQXJ0aWNsZUxpc3RFbGVtZW50IHtcbiAgICByZXR1cm4gZWxlbWVudCBhcyBBcnRpY2xlTGlzdEVsZW1lbnQ7XG4gIH1cblxuICBnZXRCdXR0b25FbGVtZW50KGVsZW1lbnQ6IEFydGljbGVFbGVtZW50KTogQXJ0aWNsZUJ1dHRvbkVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVCdXR0b25FbGVtZW50O1xuICB9XG5cbiAgZ2V0U2VwYXJhdG9yRWxlbWVudChlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEFydGljbGVTZXBhcmF0b3JFbGVtZW50IHtcbiAgICByZXR1cm4gZWxlbWVudCBhcyBBcnRpY2xlU2VwYXJhdG9yRWxlbWVudDtcbiAgfVxuXG4gIGdldEltYWdlRWxlbWVudChlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEFydGljbGVJbWFnZUVsZW1lbnQge1xuICAgIHJldHVybiBlbGVtZW50IGFzIEFydGljbGVJbWFnZUVsZW1lbnQ7XG4gIH1cblxuICBnZXRWaWRlb0VsZW1lbnQoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBBcnRpY2xlVmlkZW9FbGVtZW50IHtcbiAgICByZXR1cm4gZWxlbWVudCBhcyBBcnRpY2xlVmlkZW9FbGVtZW50O1xuICB9XG5cbiAgZ2V0Q3VzdG9tRWxlbWVudChlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEFydGljbGVDdXN0b21FbGVtZW50IHtcbiAgICByZXR1cm4gZWxlbWVudCBhcyBBcnRpY2xlQ3VzdG9tRWxlbWVudDtcbiAgfVxuXG4gIC8vID09PSBGVU5DSU9ORVMgQVVYSUxJQVJFUyBQQVJBIFBST1BTID09PVxuXG4gIGdldFF1b3RlVGV4dFByb3BzKGVsZW1lbnQ6IEFydGljbGVFbGVtZW50KSB7XG4gICAgY29uc3QgcXVvdGVFbGVtZW50ID0gdGhpcy5nZXRRdW90ZUVsZW1lbnQoZWxlbWVudCk7XG4gICAgY29uc3QgeyBhdXRob3IsIHNvdXJjZSwgLi4udGV4dFByb3BzIH0gPSBxdW90ZUVsZW1lbnQucHJvcHM7XG4gICAgcmV0dXJuIHRleHRQcm9wcztcbiAgfVxuXG4gIGdldEhpZ2hsaWdodFRleHRQcm9wcyhlbGVtZW50OiBBcnRpY2xlRWxlbWVudCkge1xuICAgIGNvbnN0IGhpZ2hsaWdodEVsZW1lbnQgPSB0aGlzLmdldEhpZ2hsaWdodEVsZW1lbnQoZWxlbWVudCk7XG4gICAgY29uc3QgeyBiYWNrZ3JvdW5kQ29sb3IsIHJvdW5kZWQsIC4uLnRleHRQcm9wcyB9ID0gaGlnaGxpZ2h0RWxlbWVudC5wcm9wcztcbiAgICByZXR1cm4gdGV4dFByb3BzO1xuICB9XG5cbiAgZ2V0SGlnaGxpZ2h0Q29sb3IoZWxlbWVudDogQXJ0aWNsZUVsZW1lbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IGhpZ2hsaWdodEVsZW1lbnQgPSB0aGlzLmdldEhpZ2hsaWdodEVsZW1lbnQoZWxlbWVudCk7XG4gICAgcmV0dXJuIGhpZ2hsaWdodEVsZW1lbnQucHJvcHMuYmFja2dyb3VuZENvbG9yIHx8ICd2YXIoLS1pb24tY29sb3ItbGlnaHQpJztcbiAgfVxuXG4gIGdldEJ1dHRvblByb3BzKGVsZW1lbnQ6IEFydGljbGVFbGVtZW50KSB7XG4gICAgY29uc3QgYnV0dG9uRWxlbWVudCA9IHRoaXMuZ2V0QnV0dG9uRWxlbWVudChlbGVtZW50KTtcbiAgICBjb25zdCB7IGFsaWdubWVudCwgLi4uYnV0dG9uUHJvcHMgfSA9IGJ1dHRvbkVsZW1lbnQucHJvcHM7XG4gICAgcmV0dXJuIGJ1dHRvblByb3BzO1xuICB9XG5cbiAgZ2V0SW1hZ2VNZXRhZGF0YShlbGVtZW50OiBBcnRpY2xlRWxlbWVudCk6IEltYWdlTWV0YWRhdGEge1xuICAgIGNvbnN0IGltYWdlRWxlbWVudCA9IHRoaXMuZ2V0SW1hZ2VFbGVtZW50KGVsZW1lbnQpO1xuICAgIGNvbnN0IHByb3BzID0gaW1hZ2VFbGVtZW50LnByb3BzO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHNyYzogcHJvcHMuc3JjLFxuICAgICAgYWx0OiBwcm9wcy5hbHQsXG4gICAgICBtb2RlOiBwcm9wcy5yb3VuZGVkID8gJ3JvdW5kZWQnIDogJ2JveCcsXG4gICAgICBzaXplOiAnbWVkaXVtJyxcbiAgICAgIHNoYWRlZDogZmFsc2UsXG4gICAgICBib3JkZXJlZDogZmFsc2UsXG4gICAgICBhbGlnbm1lbnQ6IHByb3BzLmFsaWdubWVudCB8fCAnY2VudGVyJyxcbiAgICAgIGNhcHRpb246IHByb3BzLmNhcHRpb24sXG4gICAgICBjYXB0aW9uU2l6ZTogJ21lZGl1bScgYXMgY29uc3QsXG4gICAgICB3aWR0aDogcHJvcHMubWF4V2lkdGggPyBwYXJzZUludChwcm9wcy5tYXhXaWR0aC5yZXBsYWNlKCdweCcsICcnKSkgOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxufVxuIl19