valtech-components 2.0.506 → 2.0.507

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.
@@ -69,6 +69,22 @@ export class AdSlotComponent {
69
69
  }
70
70
  return true;
71
71
  });
72
+ /**
73
+ * Indica si debe mostrar placeholder en vez de ad real.
74
+ * Activo en localhost o con Publisher ID placeholder.
75
+ */
76
+ this.isPlaceholderMode = computed(() => {
77
+ if (!isPlatformBrowser(this.platformId)) {
78
+ return false;
79
+ }
80
+ const adClient = this.adsService.adClient();
81
+ const isLocalhost = window.location.hostname === 'localhost' ||
82
+ window.location.hostname === '127.0.0.1';
83
+ const isPlaceholderClient = !adClient ||
84
+ adClient === 'ca-pub-0000000000000000' ||
85
+ adClient.includes('0000000000');
86
+ return isLocalhost || isPlaceholderClient;
87
+ });
72
88
  }
73
89
  // ===========================================================================
74
90
  // LIFECYCLE
@@ -83,6 +99,15 @@ export class AdSlotComponent {
83
99
  if (!this.shouldRender() || this.adInitialized) {
84
100
  return;
85
101
  }
102
+ // En modo placeholder, solo marcar como rendered
103
+ if (this.isPlaceholderMode()) {
104
+ this._state.set('rendered');
105
+ this.adInitialized = true;
106
+ if (this.adsService.isDebugMode()) {
107
+ console.log(`[ValtechAds] Ad slot '${this.slotId}' in PLACEHOLDER mode (localhost or invalid adClient)`);
108
+ }
109
+ return;
110
+ }
86
111
  await this.initializeAd();
87
112
  }
88
113
  ngOnDestroy() {
@@ -125,37 +150,53 @@ export class AdSlotComponent {
125
150
  [class.val-ad-slot--rendered]="state() === 'rendered'"
126
151
  [class.val-ad-slot--empty]="state() === 'empty'"
127
152
  [class.val-ad-slot--hidden]="state() === 'hidden'"
153
+ [class.val-ad-slot--placeholder]="isPlaceholderMode()"
128
154
  [class]="cssClass"
129
155
  [style.min-height]="minHeight"
130
156
  >
131
- <!-- Skeleton mientras carga -->
132
- @if (showSkeleton && state() === 'loading') {
133
- <div
134
- class="val-ad-slot__skeleton"
135
- [style.height]="minHeight"
136
- ></div>
137
- }
157
+ <!-- Placeholder mode (desarrollo local) -->
158
+ @if (isPlaceholderMode()) {
159
+ <div class="val-ad-slot__placeholder" [style.height]="minHeight">
160
+ <div class="val-ad-slot__placeholder-content">
161
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
162
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
163
+ <line x1="3" y1="9" x2="21" y2="9"/>
164
+ <line x1="9" y1="21" x2="9" y2="9"/>
165
+ </svg>
166
+ <span class="val-ad-slot__placeholder-label">Ad Placeholder</span>
167
+ <span class="val-ad-slot__placeholder-info">{{ slotId }} | {{ format }}</span>
168
+ </div>
169
+ </div>
170
+ } @else {
171
+ <!-- Skeleton mientras carga -->
172
+ @if (showSkeleton && state() === 'loading') {
173
+ <div
174
+ class="val-ad-slot__skeleton"
175
+ [style.height]="minHeight"
176
+ ></div>
177
+ }
138
178
 
139
- <!-- AdSense ins element -->
140
- <ins
141
- class="adsbygoogle val-ad-slot__container"
142
- [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
143
- [style.display]="'block'"
144
- [attr.data-ad-client]="adsService.adClient()"
145
- [attr.data-ad-slot]="adSlot || null"
146
- [attr.data-ad-format]="format"
147
- [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
148
- ></ins>
179
+ <!-- AdSense ins element -->
180
+ <ins
181
+ class="adsbygoogle val-ad-slot__container"
182
+ [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
183
+ [style.display]="'block'"
184
+ [attr.data-ad-client]="adsService.adClient()"
185
+ [attr.data-ad-slot]="adSlot || null"
186
+ [attr.data-ad-format]="format"
187
+ [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
188
+ ></ins>
189
+ }
149
190
 
150
191
  <!-- Debug info -->
151
192
  @if (adsService.isDebugMode()) {
152
193
  <div class="val-ad-slot__debug">
153
- <small>{{ slotId }} | {{ format }} | {{ state() }}</small>
194
+ <small>{{ slotId }} | {{ format }} | {{ state() }}{{ isPlaceholderMode() ? ' | PLACEHOLDER' : '' }}</small>
154
195
  </div>
155
196
  }
156
197
  </div>
157
198
  }
158
- `, isInline: true, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
199
+ `, isInline: true, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__placeholder{width:100%;background:linear-gradient(135deg,#667eea,#764ba2);border-radius:8px;display:flex;align-items:center;justify-content:center;color:#fff;border:2px dashed rgba(255,255,255,.4)}.val-ad-slot__placeholder-content{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;text-align:center}.val-ad-slot__placeholder-content svg{opacity:.8}.val-ad-slot__placeholder-label{font-weight:600;font-size:14px;letter-spacing:.5px}.val-ad-slot__placeholder-info{font-size:11px;opacity:.7;font-family:monospace}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
159
200
  }
160
201
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AdSlotComponent, decorators: [{
161
202
  type: Component,
@@ -167,37 +208,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
167
208
  [class.val-ad-slot--rendered]="state() === 'rendered'"
168
209
  [class.val-ad-slot--empty]="state() === 'empty'"
169
210
  [class.val-ad-slot--hidden]="state() === 'hidden'"
211
+ [class.val-ad-slot--placeholder]="isPlaceholderMode()"
170
212
  [class]="cssClass"
171
213
  [style.min-height]="minHeight"
172
214
  >
173
- <!-- Skeleton mientras carga -->
174
- @if (showSkeleton && state() === 'loading') {
175
- <div
176
- class="val-ad-slot__skeleton"
177
- [style.height]="minHeight"
178
- ></div>
179
- }
215
+ <!-- Placeholder mode (desarrollo local) -->
216
+ @if (isPlaceholderMode()) {
217
+ <div class="val-ad-slot__placeholder" [style.height]="minHeight">
218
+ <div class="val-ad-slot__placeholder-content">
219
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
220
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
221
+ <line x1="3" y1="9" x2="21" y2="9"/>
222
+ <line x1="9" y1="21" x2="9" y2="9"/>
223
+ </svg>
224
+ <span class="val-ad-slot__placeholder-label">Ad Placeholder</span>
225
+ <span class="val-ad-slot__placeholder-info">{{ slotId }} | {{ format }}</span>
226
+ </div>
227
+ </div>
228
+ } @else {
229
+ <!-- Skeleton mientras carga -->
230
+ @if (showSkeleton && state() === 'loading') {
231
+ <div
232
+ class="val-ad-slot__skeleton"
233
+ [style.height]="minHeight"
234
+ ></div>
235
+ }
180
236
 
181
- <!-- AdSense ins element -->
182
- <ins
183
- class="adsbygoogle val-ad-slot__container"
184
- [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
185
- [style.display]="'block'"
186
- [attr.data-ad-client]="adsService.adClient()"
187
- [attr.data-ad-slot]="adSlot || null"
188
- [attr.data-ad-format]="format"
189
- [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
190
- ></ins>
237
+ <!-- AdSense ins element -->
238
+ <ins
239
+ class="adsbygoogle val-ad-slot__container"
240
+ [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
241
+ [style.display]="'block'"
242
+ [attr.data-ad-client]="adsService.adClient()"
243
+ [attr.data-ad-slot]="adSlot || null"
244
+ [attr.data-ad-format]="format"
245
+ [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
246
+ ></ins>
247
+ }
191
248
 
192
249
  <!-- Debug info -->
193
250
  @if (adsService.isDebugMode()) {
194
251
  <div class="val-ad-slot__debug">
195
- <small>{{ slotId }} | {{ format }} | {{ state() }}</small>
252
+ <small>{{ slotId }} | {{ format }} | {{ state() }}{{ isPlaceholderMode() ? ' | PLACEHOLDER' : '' }}</small>
196
253
  </div>
197
254
  }
198
255
  </div>
199
256
  }
200
- `, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
257
+ `, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__placeholder{width:100%;background:linear-gradient(135deg,#667eea,#764ba2);border-radius:8px;display:flex;align-items:center;justify-content:center;color:#fff;border:2px dashed rgba(255,255,255,.4)}.val-ad-slot__placeholder-content{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;text-align:center}.val-ad-slot__placeholder-content svg{opacity:.8}.val-ad-slot__placeholder-label{font-weight:600;font-size:14px;letter-spacing:.5px}.val-ad-slot__placeholder-info{font-size:11px;opacity:.7;font-family:monospace}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
201
258
  }], propDecorators: { slotId: [{
202
259
  type: Input,
203
260
  args: [{ required: true }]
@@ -214,4 +271,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
214
271
  }], showSkeleton: [{
215
272
  type: Input
216
273
  }] } });
217
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWQtc2xvdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvbW9sZWN1bGVzL2FkLXNsb3QvYWQtc2xvdC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBRUgsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBR0wsTUFBTSxFQUNOLE1BQU0sRUFDTixRQUFRLEVBQ1IsV0FBVyxFQUNYLHVCQUF1QixFQUN2QixVQUFVLEdBRVgsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQzs7QUFnSC9ELE1BQU0sT0FBTyxlQUFlO0lBN0c1QjtRQThHVyxlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3hCLGVBQVUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDakMsZUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQVlqRCxxQkFBcUI7UUFDWixXQUFNLEdBQWEsTUFBTSxDQUFDO1FBRW5DLDRCQUE0QjtRQUNuQixjQUFTLEdBQUcsSUFBSSxDQUFDO1FBRTFCLDBCQUEwQjtRQUNqQixhQUFRLEdBQUcsRUFBRSxDQUFDO1FBRXZCLG9CQUFvQjtRQUNYLGNBQVMsR0FBRyxNQUFNLENBQUM7UUFFNUIsdUJBQXVCO1FBQ2QsaUJBQVksR0FBRyxJQUFJLENBQUM7UUFFN0IsOEVBQThFO1FBQzlFLFNBQVM7UUFDVCw4RUFBOEU7UUFFN0QsV0FBTSxHQUFHLE1BQU0sQ0FBYyxNQUFNLENBQUMsQ0FBQztRQUM3QyxVQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztR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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0NUOzhCQTRFMEIsTUFBTTtzQkFBaEMsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBR2hCLE1BQU07c0JBQWQsS0FBSztnQkFHRyxNQUFNO3NCQUFkLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHRyxRQUFRO3NCQUFoQixLQUFLO2dCQUdHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWQgU2xvdCBDb21wb25lbnRcbiAqXG4gKiBDb21wb25lbnRlIHN0YW5kYWxvbmUgcGFyYSBtb3N0cmFyIGFkcyBkZSBHb29nbGUgQWRTZW5zZS5cbiAqIFNlIGludGVncmEgYXV0b21hdGljYW1lbnRlIGNvbiBlbCBzZXJ2aWNpbyBkZSBBZHMgeSByZXNwZXRhIGNvbnNlbnQgKyBwcmVtaXVtLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8IS0tIEJhbm5lciBiYXNpY28gLS0+XG4gKiA8dmFsLWFkLXNsb3RcbiAqICAgc2xvdElkPVwiaG9tZXBhZ2UtdG9wXCJcbiAqICAgZm9ybWF0PVwiaG9yaXpvbnRhbFwiXG4gKiAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gKiAvPlxuICpcbiAqIDwhLS0gUmVjdGFuZ2xlIGFkIC0tPlxuICogPHZhbC1hZC1zbG90XG4gKiAgIHNsb3RJZD1cInNpZGViYXItYWRcIlxuICogICBhZFNsb3Q9XCIxMjM0NTY3ODkwXCJcbiAqICAgZm9ybWF0PVwicmVjdGFuZ2xlXCJcbiAqIC8+XG4gKlxuICogPCEtLSBBdXRvIGZvcm1hdCAoR29vZ2xlIGRlY2lkZXMpIC0tPlxuICogPHZhbC1hZC1zbG90XG4gKiAgIHNsb3RJZD1cImFydGljbGUtYWRcIlxuICogICBmb3JtYXQ9XCJhdXRvXCJcbiAqICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAqIC8+XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIE9uRGVzdHJveSxcbiAgaW5qZWN0LFxuICBzaWduYWwsXG4gIGNvbXB1dGVkLFxuICBQTEFURk9STV9JRCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIEVsZW1lbnRSZWYsXG4gIEFmdGVyVmlld0luaXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBZHNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvYWRzL2Fkcy5zZXJ2aWNlJztcbmltcG9ydCB7IEFkRm9ybWF0LCBBZFNsb3RTdGF0ZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2Fkcy90eXBlcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZhbC1hZC1zbG90JyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJ2YWwtYWQtc2xvdFwiXG4gICAgICAgIFtjbGFzcy52YWwtYWQtc2xvdC0tbG9hZGluZ109XCJzdGF0ZSgpID09PSAnbG9hZGluZydcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLXJlbmRlcmVkXT1cInN0YXRlKCkgPT09ICdyZW5kZXJlZCdcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLWVtcHR5XT1cInN0YXRlKCkgPT09ICdlbXB0eSdcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLWhpZGRlbl09XCJzdGF0ZSgpID09PSAnaGlkZGVuJ1wiXG4gICAgICAgIFtjbGFzc109XCJjc3NDbGFzc1wiXG4gICAgICAgIFtzdHlsZS5taW4taGVpZ2h0XT1cIm1pbkhlaWdodFwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gU2tlbGV0b24gbWllbnRyYXMgY2FyZ2EgLS0+XG4gICAgICAgIEBpZiAoc2hvd1NrZWxldG9uICYmIHN0YXRlKCkgPT09ICdsb2FkaW5nJykge1xuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwidmFsLWFkLXNsb3RfX3NrZWxldG9uXCJcbiAgICAgICAgICAgIFtzdHlsZS5oZWlnaHRdPVwibWluSGVpZ2h0XCJcbiAgICAgICAgICA+PC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIEFkU2Vuc2UgaW5zIGVsZW1lbnQgLS0+XG4gICAgICAgIDxpbnNcbiAgICAgICAgICBjbGFzcz1cImFkc2J5Z29vZ2xlIHZhbC1hZC1zbG90X19jb250YWluZXJcIlxuICAgICAgICAgIFtjbGFzcy52YWwtYWQtc2xvdF9fY29udGFpbmVyLS1oaWRkZW5dPVwic3RhdGUoKSA9PT0gJ2xvYWRpbmcnICYmIHNob3dTa2VsZXRvblwiXG4gICAgICAgICAgW3N0eWxlLmRpc3BsYXldPVwiJ2Jsb2NrJ1wiXG4gICAgICAgICAgW2F0dHIuZGF0YS1hZC1jbGllbnRdPVwiYWRzU2VydmljZS5hZENsaWVudCgpXCJcbiAgICAgICAgICBbYXR0ci5kYXRhLWFkLXNsb3RdPVwiYWRTbG90IHx8IG51bGxcIlxuICAgICAgICAgIFthdHRyLmRhdGEtYWQtZm9ybWF0XT1cImZvcm1hdFwiXG4gICAgICAgICAgW2F0dHIuZGF0YS1mdWxsLXdpZHRoLXJlc3BvbnNpdmVdPVwiZnVsbFdpZHRoID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgID48L2lucz5cblxuICAgICAgICA8IS0tIERlYnVnIGluZm8gLS0+XG4gICAgICAgIEBpZiAoYWRzU2VydmljZS5pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInZhbC1hZC1zbG90X19kZWJ1Z1wiPlxuICAgICAgICAgICAgPHNtYWxsPnt7IHNsb3RJZCB9fSB8IHt7IGZvcm1hdCB9fSB8IHt7IHN0YXRlKCkgfX08L3NtYWxsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC52YWwtYWQtc2xvdCB7XG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3QtLWxvYWRpbmcge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1pb24tY29sb3ItbGlnaHQsICNmNGY0ZjQpO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3QtLWVtcHR5LFxuICAgICAgLnZhbC1hZC1zbG90LS1oaWRkZW4ge1xuICAgICAgICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG4gICAgICB9XG5cbiAgICAgIC52YWwtYWQtc2xvdF9fc2tlbGV0b24ge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KFxuICAgICAgICAgIDkwZGVnLFxuICAgICAgICAgIHZhcigtLWlvbi1jb2xvci1saWdodCwgI2Y0ZjRmNCkgMjUlLFxuICAgICAgICAgIHZhcigtLWlvbi1jb2xvci1saWdodC1zaGFkZSwgI2UwZTBlMCkgNTAlLFxuICAgICAgICAgIHZhcigtLWlvbi1jb2xvci1saWdodCwgI2Y0ZjRmNCkgNzUlXG4gICAgICAgICk7XG4gICAgICAgIGJhY2tncm91bmQtc2l6ZTogMjAwJSAxMDAlO1xuICAgICAgICBhbmltYXRpb246IHNrZWxldG9uLWxvYWRpbmcgMS41cyBpbmZpbml0ZTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX2NvbnRhaW5lciB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX2NvbnRhaW5lci0taGlkZGVuIHtcbiAgICAgICAgdmlzaWJpbGl0eTogaGlkZGVuO1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB9XG5cbiAgICAgIC52YWwtYWQtc2xvdF9fZGVidWcge1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIGJvdHRvbTogMDtcbiAgICAgICAgbGVmdDogMDtcbiAgICAgICAgYmFja2dyb3VuZDogcmdiYSgwLCAwLCAwLCAwLjcpO1xuICAgICAgICBjb2xvcjogd2hpdGU7XG4gICAgICAgIHBhZGRpbmc6IDJweCA2cHg7XG4gICAgICAgIGZvbnQtc2l6ZTogMTBweDtcbiAgICAgICAgei1pbmRleDogMTAwMDtcbiAgICAgICAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgICAgIH1cblxuICAgICAgQGtleWZyYW1lcyBza2VsZXRvbi1sb2FkaW5nIHtcbiAgICAgICAgMCUge1xuICAgICAgICAgIGJhY2tncm91bmQtcG9zaXRpb246IDIwMCUgMDtcbiAgICAgICAgfVxuICAgICAgICAxMDAlIHtcbiAgICAgICAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtMjAwJSAwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQWRTbG90Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuICByZWFkb25seSBhZHNTZXJ2aWNlID0gaW5qZWN0KEFkc1NlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHBsYXRmb3JtSWQgPSBpbmplY3QoUExBVEZPUk1fSUQpO1xuICBwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnRSZWYgPSBpbmplY3QoRWxlbWVudFJlZik7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIElOUFVUUyAoQ29uZmlndXJhY2lvbiBkZWwgc2xvdClcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqIElEIHVuaWNvIGRlbCBzbG90IChwYXJhIHRyYWNraW5nIGludGVybm8pICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHNsb3RJZCE6IHN0cmluZztcblxuICAvKiogQWQgU2xvdCBJRCBkZSBBZFNlbnNlIChvcGNpb25hbCwgcGFyYSB1bmlkYWRlcyBtYW51YWxlcykgKi9cbiAgQElucHV0KCkgYWRTbG90Pzogc3RyaW5nO1xuXG4gIC8qKiBGb3JtYXRvIGRlbCBhZCAqL1xuICBASW5wdXQoKSBmb3JtYXQ6IEFkRm9ybWF0ID0gJ2F1dG8nO1xuXG4gIC8qKiBGdWxsIHdpZHRoIHJlc3BvbnNpdmUgKi9cbiAgQElucHV0KCkgZnVsbFdpZHRoID0gdHJ1ZTtcblxuICAvKiogQ1NTIGNsYXNzIGFkaWNpb25hbCAqL1xuICBASW5wdXQoKSBjc3NDbGFzcyA9ICcnO1xuXG4gIC8qKiBBbHR1cmEgbWluaW1hICovXG4gIEBJbnB1dCgpIG1pbkhlaWdodCA9ICc5MHB4JztcblxuICAvKiogTW9zdHJhciBza2VsZXRvbiAqL1xuICBASW5wdXQoKSBzaG93U2tlbGV0b24gPSB0cnVlO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBFU1RBRE9cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfc3RhdGUgPSBzaWduYWw8QWRTbG90U3RhdGU+KCdpZGxlJyk7XG4gIHJlYWRvbmx5IHN0YXRlID0gdGhpcy5fc3RhdGUuYXNSZWFkb25seSgpO1xuICBwcml2YXRlIGFkSW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICAvKiogSW5kaWNhIHNpIGVsIGNvbXBvbmVudGUgZGViZSByZW5kZXJpemFyc2UgKi9cbiAgcmVhZG9ubHkgc2hvdWxkUmVuZGVyID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIC8vIE5vIHJlbmRlcml6YXIgZW4gU1NSXG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gTm8gcmVuZGVyaXphciBzaSB1c3VhcmlvIGVzIHByZW1pdW1cbiAgICBpZiAodGhpcy5hZHNTZXJ2aWNlLmlzUHJlbWl1bVVzZXIoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIE5vIHJlbmRlcml6YXIgc2kgYWRzIGVzdGFuIGRlc2hhYmlsaXRhZG9zIHkgYXVuIG5vIGluaWNpYWxpemFkb1xuICAgIGlmICghdGhpcy5hZHNTZXJ2aWNlLmlzSW5pdGlhbGl6ZWQoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gTElGRUNZQ0xFXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGFzeW5jIG5nT25Jbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5zaG91bGRSZW5kZXIoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRlLnNldCgnbG9hZGluZycpO1xuICB9XG5cbiAgYXN5bmMgbmdBZnRlclZpZXdJbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5zaG91bGRSZW5kZXIoKSB8fCB0aGlzLmFkSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVBZCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgLy8gQWRTZW5zZSBubyByZXF1aWVyZSBjbGVhbnVwIG1hbnVhbCBjb21vIEdQVFxuICAgIHRoaXMuYWRJbml0aWFsaXplZCA9IGZhbHNlO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBSSVZBVEVcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplQWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFJlZ2lzdHJhciBzbG90IHkgY2FyZ2FyIEFkU2Vuc2Ugc2kgbm8gZXN0YSBjYXJnYWRvXG4gICAgICBjb25zdCBzdWNjZXNzID0gYXdhaXQgdGhpcy5hZHNTZXJ2aWNlLnJlZ2lzdGVyU2xvdCh0aGlzLnNsb3RJZCk7XG5cbiAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIHRoaXMuX3N0YXRlLnNldCgncmVuZGVyZWQnKTtcbiAgICAgICAgdGhpcy5hZEluaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgICBpZiAodGhpcy5hZHNTZXJ2aWNlLmlzRGVidWdNb2RlKCkpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIEFkIHNsb3QgJyR7dGhpcy5zbG90SWR9JyByZW5kZXJlZGAsIHtcbiAgICAgICAgICAgIGZvcm1hdDogdGhpcy5mb3JtYXQsXG4gICAgICAgICAgICBhZFNsb3Q6IHRoaXMuYWRTbG90LFxuICAgICAgICAgICAgZnVsbFdpZHRoOiB0aGlzLmZ1bGxXaWR0aCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fc3RhdGUuc2V0KCdlbXB0eScpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbVmFsdGVjaEFkc10gRXJyb3IgaW5pdGlhbGl6aW5nIGFkIHNsb3QgJyR7dGhpcy5zbG90SWR9JzpgLCBlcnJvcik7XG4gICAgICB0aGlzLl9zdGF0ZS5zZXQoJ2Vycm9yJyk7XG4gICAgfVxuICB9XG59XG4iXX0=
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWQtc2xvdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvbW9sZWN1bGVzL2FkLXNsb3QvYWQtc2xvdC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBRUgsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBR0wsTUFBTSxFQUNOLE1BQU0sRUFDTixRQUFRLEVBQ1IsV0FBVyxFQUNYLHVCQUF1QixFQUN2QixVQUFVLEdBRVgsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQzs7QUFxSy9ELE1BQU0sT0FBTyxlQUFlO0lBbEs1QjtRQW1LVyxlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3hCLGVBQVUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDakMsZUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQVlqRCxxQkFBcUI7UUFDWixXQUFNLEdBQWEsTUFBTSxDQUFDO1FBRW5DLDRCQUE0QjtRQUNuQixjQUFTLEdBQUcsSUFBSSxDQUFDO1FBRTFCLDBCQUEwQjtRQUNqQixhQUFRLEdBQUcsRUFBRSxDQUFDO1FBRXZCLG9CQUFvQjtRQUNYLGNBQVMsR0FBRyxNQUFNLENBQUM7UUFFNUIsdUJBQXVCO1FBQ2QsaUJBQVksR0FBRyxJQUFJLENBQUM7UUFFN0IsOEVBQThFO1FBQzlFLFNBQVM7UUFDVCw4RUFBOEU7UUFFN0QsV0FBTSxHQUFHLE1BQU0sQ0FBYyxNQUFNLENBQUMsQ0FBQztRQUM3QyxVQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztR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Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHRyxRQUFRO3NCQUFoQixLQUFLO2dCQUdHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWQgU2xvdCBDb21wb25lbnRcbiAqXG4gKiBDb21wb25lbnRlIHN0YW5kYWxvbmUgcGFyYSBtb3N0cmFyIGFkcyBkZSBHb29nbGUgQWRTZW5zZS5cbiAqIFNlIGludGVncmEgYXV0b21hdGljYW1lbnRlIGNvbiBlbCBzZXJ2aWNpbyBkZSBBZHMgeSByZXNwZXRhIGNvbnNlbnQgKyBwcmVtaXVtLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8IS0tIEJhbm5lciBiYXNpY28gLS0+XG4gKiA8dmFsLWFkLXNsb3RcbiAqICAgc2xvdElkPVwiaG9tZXBhZ2UtdG9wXCJcbiAqICAgZm9ybWF0PVwiaG9yaXpvbnRhbFwiXG4gKiAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gKiAvPlxuICpcbiAqIDwhLS0gUmVjdGFuZ2xlIGFkIC0tPlxuICogPHZhbC1hZC1zbG90XG4gKiAgIHNsb3RJZD1cInNpZGViYXItYWRcIlxuICogICBhZFNsb3Q9XCIxMjM0NTY3ODkwXCJcbiAqICAgZm9ybWF0PVwicmVjdGFuZ2xlXCJcbiAqIC8+XG4gKlxuICogPCEtLSBBdXRvIGZvcm1hdCAoR29vZ2xlIGRlY2lkZXMpIC0tPlxuICogPHZhbC1hZC1zbG90XG4gKiAgIHNsb3RJZD1cImFydGljbGUtYWRcIlxuICogICBmb3JtYXQ9XCJhdXRvXCJcbiAqICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAqIC8+XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIE9uRGVzdHJveSxcbiAgaW5qZWN0LFxuICBzaWduYWwsXG4gIGNvbXB1dGVkLFxuICBQTEFURk9STV9JRCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIEVsZW1lbnRSZWYsXG4gIEFmdGVyVmlld0luaXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBZHNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvYWRzL2Fkcy5zZXJ2aWNlJztcbmltcG9ydCB7IEFkRm9ybWF0LCBBZFNsb3RTdGF0ZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2Fkcy90eXBlcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZhbC1hZC1zbG90JyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJ2YWwtYWQtc2xvdFwiXG4gICAgICAgIFtjbGFzcy52YWwtYWQtc2xvdC0tbG9hZGluZ109XCJzdGF0ZSgpID09PSAnbG9hZGluZydcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLXJlbmRlcmVkXT1cInN0YXRlKCkgPT09ICdyZW5kZXJlZCdcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLWVtcHR5XT1cInN0YXRlKCkgPT09ICdlbXB0eSdcIlxuICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3QtLWhpZGRlbl09XCJzdGF0ZSgpID09PSAnaGlkZGVuJ1wiXG4gICAgICAgIFtjbGFzcy52YWwtYWQtc2xvdC0tcGxhY2Vob2xkZXJdPVwiaXNQbGFjZWhvbGRlck1vZGUoKVwiXG4gICAgICAgIFtjbGFzc109XCJjc3NDbGFzc1wiXG4gICAgICAgIFtzdHlsZS5taW4taGVpZ2h0XT1cIm1pbkhlaWdodFwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gUGxhY2Vob2xkZXIgbW9kZSAoZGVzYXJyb2xsbyBsb2NhbCkgLS0+XG4gICAgICAgIEBpZiAoaXNQbGFjZWhvbGRlck1vZGUoKSkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ2YWwtYWQtc2xvdF9fcGxhY2Vob2xkZXJcIiBbc3R5bGUuaGVpZ2h0XT1cIm1pbkhlaWdodFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInZhbC1hZC1zbG90X19wbGFjZWhvbGRlci1jb250ZW50XCI+XG4gICAgICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMjRcIiBoZWlnaHQ9XCIyNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIj5cbiAgICAgICAgICAgICAgICA8cmVjdCB4PVwiM1wiIHk9XCIzXCIgd2lkdGg9XCIxOFwiIGhlaWdodD1cIjE4XCIgcng9XCIyXCIgcnk9XCIyXCIvPlxuICAgICAgICAgICAgICAgIDxsaW5lIHgxPVwiM1wiIHkxPVwiOVwiIHgyPVwiMjFcIiB5Mj1cIjlcIi8+XG4gICAgICAgICAgICAgICAgPGxpbmUgeDE9XCI5XCIgeTE9XCIyMVwiIHgyPVwiOVwiIHkyPVwiOVwiLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmFsLWFkLXNsb3RfX3BsYWNlaG9sZGVyLWxhYmVsXCI+QWQgUGxhY2Vob2xkZXI8L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmFsLWFkLXNsb3RfX3BsYWNlaG9sZGVyLWluZm9cIj57eyBzbG90SWQgfX0gfCB7eyBmb3JtYXQgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPCEtLSBTa2VsZXRvbiBtaWVudHJhcyBjYXJnYSAtLT5cbiAgICAgICAgICBAaWYgKHNob3dTa2VsZXRvbiAmJiBzdGF0ZSgpID09PSAnbG9hZGluZycpIHtcbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2YWwtYWQtc2xvdF9fc2tlbGV0b25cIlxuICAgICAgICAgICAgICBbc3R5bGUuaGVpZ2h0XT1cIm1pbkhlaWdodFwiXG4gICAgICAgICAgICA+PC9kaXY+XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgPCEtLSBBZFNlbnNlIGlucyBlbGVtZW50IC0tPlxuICAgICAgICAgIDxpbnNcbiAgICAgICAgICAgIGNsYXNzPVwiYWRzYnlnb29nbGUgdmFsLWFkLXNsb3RfX2NvbnRhaW5lclwiXG4gICAgICAgICAgICBbY2xhc3MudmFsLWFkLXNsb3RfX2NvbnRhaW5lci0taGlkZGVuXT1cInN0YXRlKCkgPT09ICdsb2FkaW5nJyAmJiBzaG93U2tlbGV0b25cIlxuICAgICAgICAgICAgW3N0eWxlLmRpc3BsYXldPVwiJ2Jsb2NrJ1wiXG4gICAgICAgICAgICBbYXR0ci5kYXRhLWFkLWNsaWVudF09XCJhZHNTZXJ2aWNlLmFkQ2xpZW50KClcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hZC1zbG90XT1cImFkU2xvdCB8fCBudWxsXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtYWQtZm9ybWF0XT1cImZvcm1hdFwiXG4gICAgICAgICAgICBbYXR0ci5kYXRhLWZ1bGwtd2lkdGgtcmVzcG9uc2l2ZV09XCJmdWxsV2lkdGggPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgICA+PC9pbnM+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIERlYnVnIGluZm8gLS0+XG4gICAgICAgIEBpZiAoYWRzU2VydmljZS5pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInZhbC1hZC1zbG90X19kZWJ1Z1wiPlxuICAgICAgICAgICAgPHNtYWxsPnt7IHNsb3RJZCB9fSB8IHt7IGZvcm1hdCB9fSB8IHt7IHN0YXRlKCkgfX17eyBpc1BsYWNlaG9sZGVyTW9kZSgpID8gJyB8IFBMQUNFSE9MREVSJyA6ICcnIH19PC9zbWFsbD5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICAudmFsLWFkLXNsb3Qge1xuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgIH1cblxuICAgICAgLnZhbC1hZC1zbG90LS1sb2FkaW5nIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0taW9uLWNvbG9yLWxpZ2h0LCAjZjRmNGY0KTtcbiAgICAgIH1cblxuICAgICAgLnZhbC1hZC1zbG90LS1lbXB0eSxcbiAgICAgIC52YWwtYWQtc2xvdC0taGlkZGVuIHtcbiAgICAgICAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX3NrZWxldG9uIHtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudChcbiAgICAgICAgICA5MGRlZyxcbiAgICAgICAgICB2YXIoLS1pb24tY29sb3ItbGlnaHQsICNmNGY0ZjQpIDI1JSxcbiAgICAgICAgICB2YXIoLS1pb24tY29sb3ItbGlnaHQtc2hhZGUsICNlMGUwZTApIDUwJSxcbiAgICAgICAgICB2YXIoLS1pb24tY29sb3ItbGlnaHQsICNmNGY0ZjQpIDc1JVxuICAgICAgICApO1xuICAgICAgICBiYWNrZ3JvdW5kLXNpemU6IDIwMCUgMTAwJTtcbiAgICAgICAgYW5pbWF0aW9uOiBza2VsZXRvbi1sb2FkaW5nIDEuNXMgaW5maW5pdGU7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgICAgIH1cblxuICAgICAgLnZhbC1hZC1zbG90X19jb250YWluZXIge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgIH1cblxuICAgICAgLnZhbC1hZC1zbG90X19jb250YWluZXItLWhpZGRlbiB7XG4gICAgICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgfVxuXG4gICAgICAvKiBQbGFjZWhvbGRlciBzdHlsZXMgKi9cbiAgICAgIC52YWwtYWQtc2xvdF9fcGxhY2Vob2xkZXIge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzY2N2VlYSAwJSwgIzc2NGJhMiAxMDAlKTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgICBib3JkZXI6IDJweCBkYXNoZWQgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjQpO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX3BsYWNlaG9sZGVyLWNvbnRlbnQge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBnYXA6IDhweDtcbiAgICAgICAgcGFkZGluZzogMTZweDtcbiAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX3BsYWNlaG9sZGVyLWNvbnRlbnQgc3ZnIHtcbiAgICAgICAgb3BhY2l0eTogMC44O1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX3BsYWNlaG9sZGVyLWxhYmVsIHtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICBsZXR0ZXItc3BhY2luZzogMC41cHg7XG4gICAgICB9XG5cbiAgICAgIC52YWwtYWQtc2xvdF9fcGxhY2Vob2xkZXItaW5mbyB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTFweDtcbiAgICAgICAgb3BhY2l0eTogMC43O1xuICAgICAgICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xuICAgICAgfVxuXG4gICAgICAudmFsLWFkLXNsb3RfX2RlYnVnIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICBib3R0b206IDA7XG4gICAgICAgIGxlZnQ6IDA7XG4gICAgICAgIGJhY2tncm91bmQ6IHJnYmEoMCwgMCwgMCwgMC43KTtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgICBwYWRkaW5nOiAycHggNnB4O1xuICAgICAgICBmb250LXNpemU6IDEwcHg7XG4gICAgICAgIHotaW5kZXg6IDEwMDA7XG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XG4gICAgICB9XG5cbiAgICAgIEBrZXlmcmFtZXMgc2tlbGV0b24tbG9hZGluZyB7XG4gICAgICAgIDAlIHtcbiAgICAgICAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAyMDAlIDA7XG4gICAgICAgIH1cbiAgICAgICAgMTAwJSB7XG4gICAgICAgICAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTIwMCUgMDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEFkU2xvdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgcmVhZG9ubHkgYWRzU2VydmljZSA9IGluamVjdChBZHNTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBwbGF0Zm9ybUlkID0gaW5qZWN0KFBMQVRGT1JNX0lEKTtcbiAgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBJTlBVVFMgKENvbmZpZ3VyYWNpb24gZGVsIHNsb3QpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKiBJRCB1bmljbyBkZWwgc2xvdCAocGFyYSB0cmFja2luZyBpbnRlcm5vKSAqL1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBzbG90SWQhOiBzdHJpbmc7XG5cbiAgLyoqIEFkIFNsb3QgSUQgZGUgQWRTZW5zZSAob3BjaW9uYWwsIHBhcmEgdW5pZGFkZXMgbWFudWFsZXMpICovXG4gIEBJbnB1dCgpIGFkU2xvdD86IHN0cmluZztcblxuICAvKiogRm9ybWF0byBkZWwgYWQgKi9cbiAgQElucHV0KCkgZm9ybWF0OiBBZEZvcm1hdCA9ICdhdXRvJztcblxuICAvKiogRnVsbCB3aWR0aCByZXNwb25zaXZlICovXG4gIEBJbnB1dCgpIGZ1bGxXaWR0aCA9IHRydWU7XG5cbiAgLyoqIENTUyBjbGFzcyBhZGljaW9uYWwgKi9cbiAgQElucHV0KCkgY3NzQ2xhc3MgPSAnJztcblxuICAvKiogQWx0dXJhIG1pbmltYSAqL1xuICBASW5wdXQoKSBtaW5IZWlnaHQgPSAnOTBweCc7XG5cbiAgLyoqIE1vc3RyYXIgc2tlbGV0b24gKi9cbiAgQElucHV0KCkgc2hvd1NrZWxldG9uID0gdHJ1ZTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gRVNUQURPXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N0YXRlID0gc2lnbmFsPEFkU2xvdFN0YXRlPignaWRsZScpO1xuICByZWFkb25seSBzdGF0ZSA9IHRoaXMuX3N0YXRlLmFzUmVhZG9ubHkoKTtcbiAgcHJpdmF0ZSBhZEluaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgLyoqIEluZGljYSBzaSBlbCBjb21wb25lbnRlIGRlYmUgcmVuZGVyaXphcnNlICovXG4gIHJlYWRvbmx5IHNob3VsZFJlbmRlciA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAvLyBObyByZW5kZXJpemFyIGVuIFNTUlxuICAgIGlmICghaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIE5vIHJlbmRlcml6YXIgc2kgdXN1YXJpbyBlcyBwcmVtaXVtXG4gICAgaWYgKHRoaXMuYWRzU2VydmljZS5pc1ByZW1pdW1Vc2VyKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBObyByZW5kZXJpemFyIHNpIGFkcyBlc3RhbiBkZXNoYWJpbGl0YWRvcyB5IGF1biBubyBpbmljaWFsaXphZG9cbiAgICBpZiAoIXRoaXMuYWRzU2VydmljZS5pc0luaXRpYWxpemVkKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqIEluZGljYSBzaSBkZWJlIG1vc3RyYXIgcGxhY2Vob2xkZXIgZW4gdmV6IGRlIGFkIHJlYWwuXG4gICAqIEFjdGl2byBlbiBsb2NhbGhvc3QgbyBjb24gUHVibGlzaGVyIElEIHBsYWNlaG9sZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaXNQbGFjZWhvbGRlck1vZGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgYWRDbGllbnQgPSB0aGlzLmFkc1NlcnZpY2UuYWRDbGllbnQoKTtcbiAgICBjb25zdCBpc0xvY2FsaG9zdCA9IHdpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZSA9PT0gJ2xvY2FsaG9zdCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZSA9PT0gJzEyNy4wLjAuMSc7XG4gICAgY29uc3QgaXNQbGFjZWhvbGRlckNsaWVudCA9ICFhZENsaWVudCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRDbGllbnQgPT09ICdjYS1wdWItMDAwMDAwMDAwMDAwMDAwMCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkQ2xpZW50LmluY2x1ZGVzKCcwMDAwMDAwMDAwJyk7XG5cbiAgICByZXR1cm4gaXNMb2NhbGhvc3QgfHwgaXNQbGFjZWhvbGRlckNsaWVudDtcbiAgfSk7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIExJRkVDWUNMRVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBhc3luYyBuZ09uSW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGF0ZS5zZXQoJ2xvYWRpbmcnKTtcbiAgfVxuXG4gIGFzeW5jIG5nQWZ0ZXJWaWV3SW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVuZGVyKCkgfHwgdGhpcy5hZEluaXRpYWxpemVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRW4gbW9kbyBwbGFjZWhvbGRlciwgc29sbyBtYXJjYXIgY29tbyByZW5kZXJlZFxuICAgIGlmICh0aGlzLmlzUGxhY2Vob2xkZXJNb2RlKCkpIHtcbiAgICAgIHRoaXMuX3N0YXRlLnNldCgncmVuZGVyZWQnKTtcbiAgICAgIHRoaXMuYWRJbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAgIGlmICh0aGlzLmFkc1NlcnZpY2UuaXNEZWJ1Z01vZGUoKSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIEFkIHNsb3QgJyR7dGhpcy5zbG90SWR9JyBpbiBQTEFDRUhPTERFUiBtb2RlIChsb2NhbGhvc3Qgb3IgaW52YWxpZCBhZENsaWVudClgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVBZCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgLy8gQWRTZW5zZSBubyByZXF1aWVyZSBjbGVhbnVwIG1hbnVhbCBjb21vIEdQVFxuICAgIHRoaXMuYWRJbml0aWFsaXplZCA9IGZhbHNlO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBSSVZBVEVcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplQWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFJlZ2lzdHJhciBzbG90IHkgY2FyZ2FyIEFkU2Vuc2Ugc2kgbm8gZXN0YSBjYXJnYWRvXG4gICAgICBjb25zdCBzdWNjZXNzID0gYXdhaXQgdGhpcy5hZHNTZXJ2aWNlLnJlZ2lzdGVyU2xvdCh0aGlzLnNsb3RJZCk7XG5cbiAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIHRoaXMuX3N0YXRlLnNldCgncmVuZGVyZWQnKTtcbiAgICAgICAgdGhpcy5hZEluaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgICBpZiAodGhpcy5hZHNTZXJ2aWNlLmlzRGVidWdNb2RlKCkpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIEFkIHNsb3QgJyR7dGhpcy5zbG90SWR9JyByZW5kZXJlZGAsIHtcbiAgICAgICAgICAgIGZvcm1hdDogdGhpcy5mb3JtYXQsXG4gICAgICAgICAgICBhZFNsb3Q6IHRoaXMuYWRTbG90LFxuICAgICAgICAgICAgZnVsbFdpZHRoOiB0aGlzLmZ1bGxXaWR0aCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fc3RhdGUuc2V0KCdlbXB0eScpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbVmFsdGVjaEFkc10gRXJyb3IgaW5pdGlhbGl6aW5nIGFkIHNsb3QgJyR7dGhpcy5zbG90SWR9JzpgLCBlcnJvcik7XG4gICAgICB0aGlzLl9zdGF0ZS5zZXQoJ2Vycm9yJyk7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -28958,6 +28958,22 @@ class AdSlotComponent {
28958
28958
  }
28959
28959
  return true;
28960
28960
  });
28961
+ /**
28962
+ * Indica si debe mostrar placeholder en vez de ad real.
28963
+ * Activo en localhost o con Publisher ID placeholder.
28964
+ */
28965
+ this.isPlaceholderMode = computed(() => {
28966
+ if (!isPlatformBrowser(this.platformId)) {
28967
+ return false;
28968
+ }
28969
+ const adClient = this.adsService.adClient();
28970
+ const isLocalhost = window.location.hostname === 'localhost' ||
28971
+ window.location.hostname === '127.0.0.1';
28972
+ const isPlaceholderClient = !adClient ||
28973
+ adClient === 'ca-pub-0000000000000000' ||
28974
+ adClient.includes('0000000000');
28975
+ return isLocalhost || isPlaceholderClient;
28976
+ });
28961
28977
  }
28962
28978
  // ===========================================================================
28963
28979
  // LIFECYCLE
@@ -28972,6 +28988,15 @@ class AdSlotComponent {
28972
28988
  if (!this.shouldRender() || this.adInitialized) {
28973
28989
  return;
28974
28990
  }
28991
+ // En modo placeholder, solo marcar como rendered
28992
+ if (this.isPlaceholderMode()) {
28993
+ this._state.set('rendered');
28994
+ this.adInitialized = true;
28995
+ if (this.adsService.isDebugMode()) {
28996
+ console.log(`[ValtechAds] Ad slot '${this.slotId}' in PLACEHOLDER mode (localhost or invalid adClient)`);
28997
+ }
28998
+ return;
28999
+ }
28975
29000
  await this.initializeAd();
28976
29001
  }
28977
29002
  ngOnDestroy() {
@@ -29014,37 +29039,53 @@ class AdSlotComponent {
29014
29039
  [class.val-ad-slot--rendered]="state() === 'rendered'"
29015
29040
  [class.val-ad-slot--empty]="state() === 'empty'"
29016
29041
  [class.val-ad-slot--hidden]="state() === 'hidden'"
29042
+ [class.val-ad-slot--placeholder]="isPlaceholderMode()"
29017
29043
  [class]="cssClass"
29018
29044
  [style.min-height]="minHeight"
29019
29045
  >
29020
- <!-- Skeleton mientras carga -->
29021
- @if (showSkeleton && state() === 'loading') {
29022
- <div
29023
- class="val-ad-slot__skeleton"
29024
- [style.height]="minHeight"
29025
- ></div>
29026
- }
29027
-
29028
- <!-- AdSense ins element -->
29029
- <ins
29030
- class="adsbygoogle val-ad-slot__container"
29031
- [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
29032
- [style.display]="'block'"
29033
- [attr.data-ad-client]="adsService.adClient()"
29034
- [attr.data-ad-slot]="adSlot || null"
29035
- [attr.data-ad-format]="format"
29036
- [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
29037
- ></ins>
29046
+ <!-- Placeholder mode (desarrollo local) -->
29047
+ @if (isPlaceholderMode()) {
29048
+ <div class="val-ad-slot__placeholder" [style.height]="minHeight">
29049
+ <div class="val-ad-slot__placeholder-content">
29050
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
29051
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
29052
+ <line x1="3" y1="9" x2="21" y2="9"/>
29053
+ <line x1="9" y1="21" x2="9" y2="9"/>
29054
+ </svg>
29055
+ <span class="val-ad-slot__placeholder-label">Ad Placeholder</span>
29056
+ <span class="val-ad-slot__placeholder-info">{{ slotId }} | {{ format }}</span>
29057
+ </div>
29058
+ </div>
29059
+ } @else {
29060
+ <!-- Skeleton mientras carga -->
29061
+ @if (showSkeleton && state() === 'loading') {
29062
+ <div
29063
+ class="val-ad-slot__skeleton"
29064
+ [style.height]="minHeight"
29065
+ ></div>
29066
+ }
29067
+
29068
+ <!-- AdSense ins element -->
29069
+ <ins
29070
+ class="adsbygoogle val-ad-slot__container"
29071
+ [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
29072
+ [style.display]="'block'"
29073
+ [attr.data-ad-client]="adsService.adClient()"
29074
+ [attr.data-ad-slot]="adSlot || null"
29075
+ [attr.data-ad-format]="format"
29076
+ [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
29077
+ ></ins>
29078
+ }
29038
29079
 
29039
29080
  <!-- Debug info -->
29040
29081
  @if (adsService.isDebugMode()) {
29041
29082
  <div class="val-ad-slot__debug">
29042
- <small>{{ slotId }} | {{ format }} | {{ state() }}</small>
29083
+ <small>{{ slotId }} | {{ format }} | {{ state() }}{{ isPlaceholderMode() ? ' | PLACEHOLDER' : '' }}</small>
29043
29084
  </div>
29044
29085
  }
29045
29086
  </div>
29046
29087
  }
29047
- `, isInline: true, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29088
+ `, isInline: true, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__placeholder{width:100%;background:linear-gradient(135deg,#667eea,#764ba2);border-radius:8px;display:flex;align-items:center;justify-content:center;color:#fff;border:2px dashed rgba(255,255,255,.4)}.val-ad-slot__placeholder-content{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;text-align:center}.val-ad-slot__placeholder-content svg{opacity:.8}.val-ad-slot__placeholder-label{font-weight:600;font-size:14px;letter-spacing:.5px}.val-ad-slot__placeholder-info{font-size:11px;opacity:.7;font-family:monospace}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29048
29089
  }
29049
29090
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AdSlotComponent, decorators: [{
29050
29091
  type: Component,
@@ -29056,37 +29097,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
29056
29097
  [class.val-ad-slot--rendered]="state() === 'rendered'"
29057
29098
  [class.val-ad-slot--empty]="state() === 'empty'"
29058
29099
  [class.val-ad-slot--hidden]="state() === 'hidden'"
29100
+ [class.val-ad-slot--placeholder]="isPlaceholderMode()"
29059
29101
  [class]="cssClass"
29060
29102
  [style.min-height]="minHeight"
29061
29103
  >
29062
- <!-- Skeleton mientras carga -->
29063
- @if (showSkeleton && state() === 'loading') {
29064
- <div
29065
- class="val-ad-slot__skeleton"
29066
- [style.height]="minHeight"
29067
- ></div>
29068
- }
29069
-
29070
- <!-- AdSense ins element -->
29071
- <ins
29072
- class="adsbygoogle val-ad-slot__container"
29073
- [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
29074
- [style.display]="'block'"
29075
- [attr.data-ad-client]="adsService.adClient()"
29076
- [attr.data-ad-slot]="adSlot || null"
29077
- [attr.data-ad-format]="format"
29078
- [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
29079
- ></ins>
29104
+ <!-- Placeholder mode (desarrollo local) -->
29105
+ @if (isPlaceholderMode()) {
29106
+ <div class="val-ad-slot__placeholder" [style.height]="minHeight">
29107
+ <div class="val-ad-slot__placeholder-content">
29108
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
29109
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
29110
+ <line x1="3" y1="9" x2="21" y2="9"/>
29111
+ <line x1="9" y1="21" x2="9" y2="9"/>
29112
+ </svg>
29113
+ <span class="val-ad-slot__placeholder-label">Ad Placeholder</span>
29114
+ <span class="val-ad-slot__placeholder-info">{{ slotId }} | {{ format }}</span>
29115
+ </div>
29116
+ </div>
29117
+ } @else {
29118
+ <!-- Skeleton mientras carga -->
29119
+ @if (showSkeleton && state() === 'loading') {
29120
+ <div
29121
+ class="val-ad-slot__skeleton"
29122
+ [style.height]="minHeight"
29123
+ ></div>
29124
+ }
29125
+
29126
+ <!-- AdSense ins element -->
29127
+ <ins
29128
+ class="adsbygoogle val-ad-slot__container"
29129
+ [class.val-ad-slot__container--hidden]="state() === 'loading' && showSkeleton"
29130
+ [style.display]="'block'"
29131
+ [attr.data-ad-client]="adsService.adClient()"
29132
+ [attr.data-ad-slot]="adSlot || null"
29133
+ [attr.data-ad-format]="format"
29134
+ [attr.data-full-width-responsive]="fullWidth ? 'true' : null"
29135
+ ></ins>
29136
+ }
29080
29137
 
29081
29138
  <!-- Debug info -->
29082
29139
  @if (adsService.isDebugMode()) {
29083
29140
  <div class="val-ad-slot__debug">
29084
- <small>{{ slotId }} | {{ format }} | {{ state() }}</small>
29141
+ <small>{{ slotId }} | {{ format }} | {{ state() }}{{ isPlaceholderMode() ? ' | PLACEHOLDER' : '' }}</small>
29085
29142
  </div>
29086
29143
  }
29087
29144
  </div>
29088
29145
  }
29089
- `, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
29146
+ `, styles: [".val-ad-slot{position:relative;display:flex;justify-content:center;align-items:center;overflow:hidden;width:100%}.val-ad-slot--loading{background-color:var(--ion-color-light, #f4f4f4)}.val-ad-slot--empty,.val-ad-slot--hidden{display:none!important}.val-ad-slot__skeleton{width:100%;background:linear-gradient(90deg,var(--ion-color-light, #f4f4f4) 25%,var(--ion-color-light-shade, #e0e0e0) 50%,var(--ion-color-light, #f4f4f4) 75%);background-size:200% 100%;animation:skeleton-loading 1.5s infinite;border-radius:4px}.val-ad-slot__container{width:100%}.val-ad-slot__container--hidden{visibility:hidden;position:absolute}.val-ad-slot__placeholder{width:100%;background:linear-gradient(135deg,#667eea,#764ba2);border-radius:8px;display:flex;align-items:center;justify-content:center;color:#fff;border:2px dashed rgba(255,255,255,.4)}.val-ad-slot__placeholder-content{display:flex;flex-direction:column;align-items:center;gap:8px;padding:16px;text-align:center}.val-ad-slot__placeholder-content svg{opacity:.8}.val-ad-slot__placeholder-label{font-weight:600;font-size:14px;letter-spacing:.5px}.val-ad-slot__placeholder-info{font-size:11px;opacity:.7;font-family:monospace}.val-ad-slot__debug{position:absolute;bottom:0;left:0;background:#000000b3;color:#fff;padding:2px 6px;font-size:10px;z-index:1000;font-family:monospace}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
29090
29147
  }], propDecorators: { slotId: [{
29091
29148
  type: Input,
29092
29149
  args: [{ required: true }]