Before / After Image
Compare two photos with a divider you can drag, click or move from the keyboard. Horizontal or vertical, any frame ratio, optional zoom, pan and fullscreen. Both photos are in the HTML with their alt text, so visitors without JavaScript still see them side by side. Everything is set in the Etch props panel.
Paste it on the Etch canvas with Ctrl+V or ⌘V, then click Save.
{
"type": "block",
"gutenbergBlock": {
"blockName": "etch/component",
"attrs": {
"ref": 119,
"attributes": {}
},
"innerBlocks": [],
"innerHTML": "\n\n",
"innerContent": [
"\n",
"\n"
]
},
"timestamp": "2026-10-13T14:58:16.088Z",
"styles": {
"7vz25q6": {
"type": "class",
"selector": ".ed-before-after",
"collection": "default",
"css": "/* Styling guide: delete the comment marks around one line to set that token for every before/after image. */\n /* An uncommented line also wins over the same token on a parent class. For one section only, leave it commented and set the token on a parent class. */\n /* An Etch component instance has no class field of its own; style a parent element instead. */\n /* The --ci-before-after variables belong to the bundled library; set these component tokens instead. */\n\n /* Viewport */\n /* --ed-before-after-radius: var(--radius, 0.25rem); */\n /* --ed-before-after-surface: var(--neutral-ultra-light, #eee); */\n /* --ed-before-after-shadow: none; */\n /* --ed-before-after-fullscreen-bg: #000; */\n\n /* Crop focus (object-position); the before and after tokens fall back to the shared one */\n /* --ed-before-after-image-position: 50% 50%; */\n /* --ed-before-after-before-image-position: var(--ed-before-after-image-position, 50% 50%); */\n /* --ed-before-after-after-image-position: var(--ed-before-after-image-position, 50% 50%); */\n\n /* Divider and handle */\n /* --ed-before-after-divider-width: 3px; */\n /* --ed-before-after-divider-color: #fff; */\n /* --ed-before-after-divider-shadow: none; */\n /* Handle size is the hit area and default grip size; values below 44px use 44px. */\n /* --ed-before-after-handle-size: 44px; */\n /* Grip size is only the visible circle and may be smaller; the hit area stays at least 44px. */\n /* --ed-before-after-handle-grip-size: max(44px, var(--ed-before-after-handle-size, 44px)); */\n /* --ed-before-after-handle-bg: #fff; */\n /* --ed-before-after-handle-hover-bg: var(--ed-before-after-handle-bg, #fff); */\n /* --ed-before-after-handle-color: #222; */\n /* --ed-before-after-handle-border: var(--border, 1px solid #555); */\n /* --ed-before-after-handle-radius: 50%; */\n /* --ed-before-after-handle-shadow: none; */\n /* --ed-before-after-handle-icon-size: 20px; */\n\n /* Labels (also the editor and no-JavaScript captions); control-inset is their distance from the image edge */\n /* --ed-before-after-label-bg: #222; */\n /* --ed-before-after-label-color: #fff; */\n /* --ed-before-after-label-size: var(--text-s, 0.875rem); */\n /* --ed-before-after-label-weight: 600; */\n /* --ed-before-after-label-font-family: inherit; */\n /* --ed-before-after-label-padding: 0.35em 0.7em; */\n /* --ed-before-after-label-radius: var(--ed-before-after-radius, var(--radius, 0.25rem)); */\n /* --ed-before-after-control-inset: var(--space-xs, 0.75rem); */\n\n /* Zoom, pan and fullscreen buttons, zoom hint; button size values below 44px use 44px */\n /* --ed-before-after-button-size: 44px; */\n /* --ed-before-after-button-inset: var(--space-xs, 0.75rem); */\n /* --ed-before-after-controls-bg: #fff; */\n /* --ed-before-after-controls-color: #222; */\n /* --ed-before-after-controls-hover-bg: rgb(0 0 0 / 0.08); */\n /* --ed-before-after-controls-radius: var(--ed-before-after-radius, var(--radius, 0.5rem)); */\n /* --ed-before-after-controls-shadow: none; */\n /* --ed-before-after-hint-bg: rgb(0 0 0 / 0.75); */\n /* --ed-before-after-hint-color: #fff; */\n /* --ed-before-after-hint-size: var(--text-xs, 0.8125rem); */\n\n /* Focus; the halo is the ring between the handle and the focus outline */\n /* --ed-before-after-focus-color: var(--focus-color, #005fcc); */\n /* --ed-before-after-focus-width: 3px; */\n /* --ed-before-after-focus-halo: #fff; */\n/*! Third-party CSS, mechanically scoped.\n@cloudimage/before-after 1.0.4 — Scaleflex\nhttps://github.com/scaleflex/cloudimage-before-after\nhttps://www.npmjs.com/package/@cloudimage/before-after\n\nMIT License\n\nCopyright (c) 2024 Scaleflex\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nEtchDeveloper applies a version-pinned accessibility patch to the bundled vendor JavaScript: click alternatives, gesture click suppression, public pan/cancel hooks, repeatable entrance animation and a component-level native fullscreen target.\n*/\n.ci-before-after-container{--ci-before-after-handle-width: 4px;--ci-before-after-handle-color: #ffffff;--ci-before-after-handle-shadow: 0 0 8px rgba(0, 0, 0, .3);--ci-before-after-grip-size: 44px;--ci-before-after-grip-bg: #ffffff;--ci-before-after-grip-border: 2px solid rgba(0, 0, 0, .1);--ci-before-after-grip-border-radius: 50%;--ci-before-after-grip-shadow: 0 2px 8px rgba(0, 0, 0, .2);--ci-before-after-grip-icon-color: #333333;--ci-before-after-grip-icon-size: 20px;--ci-before-after-grip-hover-bg: #f0f0f0;--ci-before-after-grip-hover-shadow: 0 4px 16px rgba(0, 0, 0, .25);--ci-before-after-grip-active-bg: #e0e0e0;--ci-before-after-grip-active-scale: .95;--ci-before-after-label-font-family: inherit;--ci-before-after-label-font-size: 14px;--ci-before-after-label-font-weight: 600;--ci-before-after-label-color: #ffffff;--ci-before-after-label-bg: rgba(0, 0, 0, .5);--ci-before-after-label-padding: 6px 14px;--ci-before-after-label-border-radius: 6px;--ci-before-after-label-offset-x: 12px;--ci-before-after-label-offset-y: 12px;--ci-before-after-label-backdrop-filter: blur(4px);--ci-before-after-handle-transition: .15s ease;--ci-before-after-slide-transition: 0ms;--ci-before-after-animate-duration: .8s;--ci-before-after-animate-easing: ease-out;--ci-before-after-zoom-controls-bg: rgba(255, 255, 255, .9);--ci-before-after-zoom-controls-color: #333333;--ci-before-after-zoom-controls-border-radius: 8px;--ci-before-after-zoom-controls-shadow: 0 2px 8px rgba(0, 0, 0, .15)}.ci-before-after-theme-dark{--ci-before-after-handle-color: #1a1a1a;--ci-before-after-handle-shadow: 0 0 8px rgba(255, 255, 255, .2);--ci-before-after-grip-bg: #1a1a1a;--ci-before-after-grip-border: 2px solid rgba(255, 255, 255, .2);--ci-before-after-grip-shadow: 0 2px 8px rgba(0, 0, 0, .5);--ci-before-after-grip-icon-color: #f0f0f0;--ci-before-after-grip-hover-bg: #2a2a2a;--ci-before-after-grip-active-bg: #333333;--ci-before-after-label-bg: rgba(0, 0, 0, .45);--ci-before-after-label-color: #f0f0f0;--ci-before-after-zoom-controls-bg: rgba(30, 30, 30, .9);--ci-before-after-zoom-controls-color: #f0f0f0}.ci-before-after-container{position:relative;overflow:hidden;width:100%;border-radius:var(--ci-before-after-border-radius, 0px);box-shadow:var(--ci-before-after-shadow, none);user-select:none;-webkit-user-select:none;touch-action:pan-y;line-height:0}.ci-before-after-container--vertical{touch-action:pan-x}.ci-before-after-container--fullscreen{background:#000;display:flex;align-items:center;justify-content:center;width:100vw;height:100vh}.ci-before-after-container--fullscreen .ci-before-after-viewport{height:auto}.ci-before-after-container--fullscreen .ci-before-after-wrapper{max-height:100vh}.ci-before-after-container--fullscreen .ci-before-after-image{object-fit:contain}.ci-before-after-container--dragging{cursor:ew-resize}.ci-before-after-container--vertical.ci-before-after-container--dragging{cursor:ns-resize}.ci-before-after-viewport{position:relative;width:100%;height:100%;transform-origin:0 0}.ci-before-after-viewport--zoomable{will-change:transform}.ci-before-after-wrapper{position:relative;width:100%;overflow:hidden}.ci-before-after-image{display:block;width:100%;height:100%;object-fit:cover}.ci-before-after-before{display:block;width:100%}.ci-before-after-after{position:absolute;top:0;left:0;width:100%;height:100%}.ci-before-after-clip{position:absolute;top:0;left:0;right:0;bottom:0}.ci-before-after-handle{position:absolute;top:0;bottom:0;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:10;transform:translate(-50%);cursor:ew-resize;outline:none}.ci-before-after-handle:focus-visible .ci-before-after-handle-grip{outline:3px solid #4d90fe;outline-offset:2px}.ci-before-after-container--vertical .ci-before-after-handle{top:auto;bottom:auto;left:0;right:0;flex-direction:row;transform:translateY(-50%);cursor:ns-resize}.ci-before-after-handle-line{flex:1;width:var(--ci-before-after-handle-width);background:var(--ci-before-after-handle-color);box-shadow:var(--ci-before-after-handle-shadow)}.ci-before-after-container--vertical .ci-before-after-handle-line{width:auto;height:var(--ci-before-after-handle-width);flex:1}.ci-before-after-handle-grip{display:flex;align-items:center;justify-content:center;width:var(--ci-before-after-grip-size);height:var(--ci-before-after-grip-size);background:var(--ci-before-after-grip-bg);border:var(--ci-before-after-grip-border);border-radius:var(--ci-before-after-grip-border-radius);box-shadow:var(--ci-before-after-grip-shadow);color:var(--ci-before-after-grip-icon-color);flex-shrink:0;transition:background .15s ease,box-shadow .15s ease,transform .15s ease}.ci-before-after-handle-grip svg{width:var(--ci-before-after-grip-icon-size);height:var(--ci-before-after-grip-icon-size)}.ci-before-after-handle-grip:hover,.ci-before-after-handle:hover .ci-before-after-handle-grip{background:var(--ci-before-after-grip-hover-bg);box-shadow:var(--ci-before-after-grip-hover-shadow);transform:scale(1.1)}.ci-before-after-container--dragging .ci-before-after-handle-grip{background:var(--ci-before-after-grip-active-bg);transform:scale(var(--ci-before-after-grip-active-scale))}.ci-before-after-handle--line .ci-before-after-handle-grip,.ci-before-after-handle--line .ci-before-after-handle-grip--pill{width:8px;height:32px;border-radius:4px}.ci-before-after-container--vertical .ci-before-after-handle--line .ci-before-after-handle-grip{width:32px;height:8px}.ci-before-after-handle--circle .ci-before-after-handle-line{display:none}.ci-before-after-label{position:absolute;z-index:5;font-family:var(--ci-before-after-label-font-family);font-size:var(--ci-before-after-label-font-size);font-weight:var(--ci-before-after-label-font-weight);color:var(--ci-before-after-label-color);background:var(--ci-before-after-label-bg);padding:var(--ci-before-after-label-padding);border-radius:var(--ci-before-after-label-border-radius);backdrop-filter:var(--ci-before-after-label-backdrop-filter);-webkit-backdrop-filter:var(--ci-before-after-label-backdrop-filter);pointer-events:none;line-height:1.2;transition:opacity .2s ease;opacity:1}.ci-before-after-label--hidden{opacity:0}.ci-before-after-container--horizontal .ci-before-after-label--top.ci-before-after-label-before{top:var(--ci-before-after-label-offset-y);left:25%;transform:translate(-50%)}.ci-before-after-container--horizontal .ci-before-after-label--top.ci-before-after-label-after{top:var(--ci-before-after-label-offset-y);left:75%;transform:translate(-50%)}.ci-before-after-container--horizontal .ci-before-after-label--bottom.ci-before-after-label-before{bottom:var(--ci-before-after-label-offset-y);left:25%;transform:translate(-50%)}.ci-before-after-container--horizontal .ci-before-after-label--bottom.ci-before-after-label-after{bottom:var(--ci-before-after-label-offset-y);left:75%;transform:translate(-50%)}.ci-before-after-container--vertical .ci-before-after-label--top.ci-before-after-label-before{top:var(--ci-before-after-label-offset-y);left:var(--ci-before-after-label-offset-x)}.ci-before-after-container--vertical .ci-before-after-label--top.ci-before-after-label-after{bottom:var(--ci-before-after-label-offset-y);left:var(--ci-before-after-label-offset-x)}.ci-before-after-container--vertical .ci-before-after-label--bottom.ci-before-after-label-before{top:var(--ci-before-after-label-offset-y);right:var(--ci-before-after-label-offset-x)}.ci-before-after-container--vertical .ci-before-after-label--bottom.ci-before-after-label-after{bottom:var(--ci-before-after-label-offset-y);right:var(--ci-before-after-label-offset-x)}.ci-before-after-container--vertical.ci-before-after-container--zoom-left .ci-before-after-label--top.ci-before-after-label-before,.ci-before-after-container--vertical.ci-before-after-container--zoom-left .ci-before-after-label--top.ci-before-after-label-after{left:calc(var(--ci-before-after-label-offset-x) + 44px)}.ci-before-after-zoom-controls{position:absolute;z-index:20;display:flex;gap:2px;background:var(--ci-before-after-zoom-controls-bg);border-radius:var(--ci-before-after-zoom-controls-border-radius);box-shadow:var(--ci-before-after-zoom-controls-shadow);padding:0;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.ci-before-after-zoom-controls button{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:transparent;color:var(--ci-before-after-zoom-controls-color);cursor:pointer;border-radius:6px;padding:0;transition:background .15s ease}.ci-before-after-zoom-controls button:hover{background:#00000014}.ci-before-after-theme-dark .ci-before-after-zoom-controls button:hover{background:#ffffff1f}.ci-before-after-zoom-controls button:focus-visible{outline:2px solid #4d90fe;outline-offset:-2px}.ci-before-after-zoom-controls--top-left{top:12px;left:12px}.ci-before-after-zoom-controls--top-center{top:12px;left:50%;transform:translate(-50%)}.ci-before-after-zoom-controls--top-right{top:12px;right:12px}.ci-before-after-zoom-controls--bottom-left{bottom:12px;left:12px}.ci-before-after-zoom-controls--bottom-center{bottom:12px;left:50%;transform:translate(-50%)}.ci-before-after-zoom-controls--bottom-right{bottom:12px;right:12px}.ci-before-after-fullscreen-btn{position:absolute;top:12px;right:12px;z-index:20;display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:var(--ci-before-after-zoom-controls-bg);color:var(--ci-before-after-zoom-controls-color);border-radius:8px;cursor:pointer;box-shadow:var(--ci-before-after-zoom-controls-shadow);padding:0;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:background .15s ease}.ci-before-after-fullscreen-btn:hover{background:#e6e6e6f2}.ci-before-after-theme-dark .ci-before-after-fullscreen-btn:hover{background:#323232f2}.ci-before-after-fullscreen-btn:focus-visible{outline:2px solid #4d90fe;outline-offset:2px}.ci-before-after-container--zoom-top-right .ci-before-after-fullscreen-btn{right:132px}.ci-before-after-container--zoom-top.ci-before-after-container--horizontal .ci-before-after-label--top{top:auto;bottom:var(--ci-before-after-label-offset-y)}.ci-before-after-scroll-hint{position:absolute;bottom:50%;left:50%;transform:translate(-50%,50%);z-index:30;background:#000000bf;color:#fff;padding:8px 16px;border-radius:8px;font-size:13px;font-weight:500;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .2s ease;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);line-height:1.4}.ci-before-after-scroll-hint--visible{opacity:1}.ci-before-after-loading .ci-before-after-wrapper{aspect-ratio:var(--ci-before-after-aspect-ratio, auto);min-height:200px;background:linear-gradient(90deg,#f0f0f0 25%,#e0e0e0,#f0f0f0 75%);background-size:200% 100%;animation:ed-before-after-vendor-shimmer 1.5s infinite}.ci-before-after-theme-dark.ci-before-after-loading .ci-before-after-wrapper{background:linear-gradient(90deg,#2a2a2a 25%,#333,#2a2a2a 75%);background-size:200% 100%}@keyframes ed-before-after-vendor-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.ci-before-after-container--hover-mode{cursor:ew-resize}.ci-before-after-container--vertical.ci-before-after-container--hover-mode{cursor:ns-resize}.ci-before-after-container--click-mode{cursor:pointer}@media(prefers-reduced-motion:reduce){.ci-before-after-container,.ci-before-after-container *{animation:none!important;transition-duration:.01ms!important}}\n/* EtchDeveloper theme */\n min-inline-size: 0;\n inline-size: 100%;\n --_ed-ba-ratio: 4 / 3;\n --_ed-ba-fit: cover;\n --_ed-ba-button: max(44px, var(--ed-before-after-button-size, 44px));\n --_ed-ba-button-inset: var(--ed-before-after-button-inset, var(--space-xs, .75rem));\n --_ed-ba-hit: max(44px, var(--ed-before-after-handle-size, 44px));\n &[data-ed-ba-comparison-aspect-ratio=\"16 / 9\"] { --_ed-ba-ratio: 16 / 9; }\n &[data-ed-ba-comparison-aspect-ratio=\"1 / 1\"] { --_ed-ba-ratio: 1 / 1; }\n &[data-ed-ba-comparison-aspect-ratio=\"3 / 4\"] { --_ed-ba-ratio: 3 / 4; }\n &[data-ed-ba-comparison-object-fit=\"contain\"] { --_ed-ba-fit: contain; }\n & > .ed-before-after__fallback { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); background: var(--ed-before-after-surface, var(--neutral-ultra-light, #eee)); border-radius: var(--ed-before-after-radius, var(--radius, .25rem)); box-shadow: var(--ed-before-after-shadow, none); overflow: hidden; }\n & .ed-before-after__figure { display: grid; grid-template-columns: minmax(0, 1fr); position: relative; margin: 0; min-inline-size: 0; }\n /* The ratio spacer also works with missing media. Captions contribute their\n full intrinsic height, so long no-JS/editor text can grow beyond the ratio. */\n & .ed-before-after__figure::before { content: \"\"; grid-area: 1 / 1; inline-size: 100%; aspect-ratio: calc(var(--_ed-ba-ratio) / 2); }\n & .ed-before-after__figure img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: var(--_ed-ba-fit); object-position: var(--ed-before-after-image-position, 50% 50%); }\n & .ed-before-after__figure:first-of-type img { object-position: var(--ed-before-after-before-image-position, var(--ed-before-after-image-position, 50% 50%)); }\n & .ed-before-after__figure:last-of-type img { object-position: var(--ed-before-after-after-image-position, var(--ed-before-after-image-position, 50% 50%)); }\n & .ed-before-after__caption { grid-area: 1 / 1; align-self: end; position: relative; min-inline-size: 0; text-align: center; color: var(--ed-before-after-label-color, #fff); background: var(--ed-before-after-label-bg, #222); font-family: var(--ed-before-after-label-font-family, inherit); font-size: var(--ed-before-after-label-size, var(--text-s, .875rem)); font-weight: var(--ed-before-after-label-weight, 600); line-height: 1.2; padding: var(--ed-before-after-label-padding, .35em .7em); overflow-wrap: anywhere; }\n &[data-ed-ba-content-show-labels=\"false\"] .ed-before-after__caption { display: none; }\n &[data-ed-ba-ready=\"true\"] > .ed-before-after__fallback { display: none; }\n & > .ed-before-after__mount[hidden] { display: none; }\n & > .ci-before-after-container {\n aspect-ratio: var(--_ed-ba-ratio);\n /* A clipped endpoint must not become a hidden scroll area when focused. */\n overflow: clip;\n background: var(--ed-before-after-surface, var(--neutral-ultra-light, #eee));\n --ci-before-after-border-radius: var(--ed-before-after-radius, var(--radius, .25rem));\n --ci-before-after-shadow: var(--ed-before-after-shadow, none);\n --ci-before-after-handle-width: var(--ed-before-after-divider-width, 3px);\n --ci-before-after-handle-color: var(--ed-before-after-divider-color, #fff);\n --ci-before-after-handle-shadow: var(--ed-before-after-divider-shadow, none);\n --ci-before-after-grip-size: var(--ed-before-after-handle-grip-size, var(--_ed-ba-hit));\n --ci-before-after-grip-bg: var(--ed-before-after-handle-bg, #fff);\n --ci-before-after-grip-icon-color: var(--ed-before-after-handle-color, #222);\n --ci-before-after-grip-icon-size: var(--ed-before-after-handle-icon-size, 20px);\n --ci-before-after-grip-border: var(--ed-before-after-handle-border, var(--border, 1px solid #555));\n --ci-before-after-grip-border-radius: var(--ed-before-after-handle-radius, 50%);\n --ci-before-after-grip-shadow: var(--ed-before-after-handle-shadow, none);\n --ci-before-after-grip-hover-shadow: var(--ed-before-after-handle-shadow, none);\n --ci-before-after-grip-hover-bg: var(--ed-before-after-handle-hover-bg, var(--ed-before-after-handle-bg, #fff));\n --ci-before-after-grip-active-bg: var(--ed-before-after-handle-hover-bg, var(--ed-before-after-handle-bg, #fff));\n --ci-before-after-grip-active-scale: 1;\n --ci-before-after-label-bg: var(--ed-before-after-label-bg, #222);\n --ci-before-after-label-color: var(--ed-before-after-label-color, #fff);\n --ci-before-after-label-font-family: var(--ed-before-after-label-font-family, inherit);\n --ci-before-after-label-font-size: var(--ed-before-after-label-size, var(--text-s, .875rem));\n --ci-before-after-label-font-weight: var(--ed-before-after-label-weight, 600);\n --ci-before-after-label-padding: var(--ed-before-after-label-padding, .35em .7em);\n --ci-before-after-label-border-radius: var(--ed-before-after-label-radius, var(--ed-before-after-radius, var(--radius, .25rem)));\n --ci-before-after-label-backdrop-filter: none;\n --ci-before-after-label-offset-x: var(--ed-before-after-control-inset, var(--space-xs, .75rem));\n --ci-before-after-label-offset-y: var(--ed-before-after-control-inset, var(--space-xs, .75rem));\n --ci-before-after-zoom-controls-bg: var(--ed-before-after-controls-bg, #fff);\n --ci-before-after-zoom-controls-color: var(--ed-before-after-controls-color, #222);\n --ci-before-after-zoom-controls-border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem)));\n --ci-before-after-zoom-controls-shadow: var(--ed-before-after-controls-shadow, none);\n /* Vertical page scrolling and page pinch-zoom stay with the browser in both orientations. */\n touch-action: pan-y pinch-zoom;\n }\n /* With the component zoom on, the library handles a two-finger pinch itself. */\n &[data-ed-ba-zoom-enabled=\"true\"] > .ci-before-after-container { touch-action: pan-y; }\n /* Fullscreen shows the whole image on a dark stage, not the inline surface or rounding. */\n &:fullscreen { display: block; overflow: auto; inline-size: 100%; block-size: 100%; background: var(--ed-before-after-fullscreen-bg, #000); }\n & > .ci-before-after-container.ci-before-after-container--fullscreen { aspect-ratio: auto; inline-size: 100%; block-size: 100dvh; background: var(--ed-before-after-fullscreen-bg, #000); --ci-before-after-border-radius: 0; }\n & .ci-before-after-container--fullscreen .ci-before-after-viewport { height: 100%; }\n & .ci-before-after-wrapper { block-size: 100%; min-block-size: 0; }\n & .ci-before-after-image { block-size: 100%; object-fit: var(--_ed-ba-fit); object-position: var(--ed-before-after-image-position, 50% 50%); }\n & .ci-before-after-before { object-position: var(--ed-before-after-before-image-position, var(--ed-before-after-image-position, 50% 50%)); }\n & .ci-before-after-after { object-position: var(--ed-before-after-after-image-position, var(--ed-before-after-image-position, 50% 50%)); }\n & .ci-before-after-loading .ci-before-after-wrapper { min-height: 0; background: var(--ed-before-after-surface, var(--neutral-ultra-light, #eee)); animation: none; }\n /* The handle column (a row when vertical) is the hit area; the grip inside may be smaller. */\n & .ci-before-after-handle { min-inline-size: var(--_ed-ba-hit); touch-action: none; }\n & .ci-before-after-container--vertical .ci-before-after-handle { min-block-size: var(--_ed-ba-hit); }\n & .ci-before-after-handle-grip:hover, & .ci-before-after-handle:hover .ci-before-after-handle-grip { transform: none; }\n /* Two-tone ring: the halo keeps the outline visible on any photo. */\n & .ci-before-after-handle:focus-visible .ci-before-after-handle-grip { outline: var(--ed-before-after-focus-width, 3px) solid var(--ed-before-after-focus-color, var(--focus-color, #005fcc)); outline-offset: 2px; box-shadow: 0 0 0 2px var(--ed-before-after-focus-halo, #fff); }\n & .ci-before-after-label { box-sizing: border-box; inline-size: max-content; max-inline-size: 44%; overflow-wrap: anywhere; text-align: center; }\n & .ci-before-after-zoom-controls, & .ci-before-after-fullscreen-btn, & .ci-before-after-scroll-hint { backdrop-filter: none; -webkit-backdrop-filter: none; }\n & .ci-before-after-zoom-controls button, & .ci-before-after-fullscreen-btn, & .ed-before-after__pan-button { min-inline-size: var(--_ed-ba-button); min-block-size: var(--_ed-ba-button); }\n & .ci-before-after-zoom-controls--top-left { top: var(--_ed-ba-button-inset); left: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls--top-center { top: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls--top-right { top: var(--_ed-ba-button-inset); right: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls--bottom-left { bottom: var(--_ed-ba-button-inset); left: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls--bottom-center { bottom: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls--bottom-right { bottom: var(--_ed-ba-button-inset); right: var(--_ed-ba-button-inset); }\n & .ci-before-after-fullscreen-btn { top: var(--_ed-ba-button-inset); right: var(--_ed-ba-button-inset); }\n & .ci-before-after-zoom-controls button { border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem))); }\n & .ci-before-after-fullscreen-btn { border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem))); }\n & .ci-before-after-zoom-controls button:hover { background: var(--ed-before-after-controls-hover-bg, rgb(0 0 0 / .08)); }\n & .ci-before-after-fullscreen-btn:hover { background: linear-gradient(var(--ed-before-after-controls-hover-bg, rgb(0 0 0 / .08)) 0 0) var(--ed-before-after-controls-bg, #fff); }\n & .ci-before-after-zoom-controls button:focus-visible, & .ci-before-after-fullscreen-btn:focus-visible { outline: var(--ed-before-after-focus-width, 3px) solid var(--ed-before-after-focus-color, var(--focus-color, #005fcc)); outline-offset: calc(-1 * var(--ed-before-after-focus-width, 3px)); }\n /* Beside a top-right zoom bar: three buttons, two 2px gaps and an 8px space. */\n & .ci-before-after-container--zoom-top-right .ci-before-after-fullscreen-btn { right: calc(var(--_ed-ba-button-inset) + 3 * var(--_ed-ba-button) + 12px); }\n & .ci-before-after-scroll-hint { white-space: normal; max-inline-size: 90%; text-align: center; background: var(--ed-before-after-hint-bg, rgb(0 0 0 / .75)); color: var(--ed-before-after-hint-color, #fff); font-size: var(--ed-before-after-hint-size, var(--text-xs, .8125rem)); }\n & .ed-before-after__pan-controls { position: absolute; inset-block-start: 50%; inset-inline-start: var(--_ed-ba-button-inset); transform: translateY(-50%); z-index: 20; display: flex; gap: 2px; background: var(--ed-before-after-controls-bg, #fff); border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem))); box-shadow: var(--ed-before-after-controls-shadow, none); }\n & .ed-before-after__pan-button { display: flex; align-items: center; justify-content: center; flex: 0 0 var(--_ed-ba-button); block-size: var(--_ed-ba-button); border: 0; padding: 0; color: var(--ed-before-after-controls-color, #222); background: transparent; border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem))); cursor: pointer; }\n & .ed-before-after__pan-button svg { inline-size: 20px; block-size: 20px; }\n & .ed-before-after__pan-button:hover { background: var(--ed-before-after-controls-hover-bg, rgb(0 0 0 / .08)); }\n & .ed-before-after__pan-button:focus-visible { outline: var(--ed-before-after-focus-width, 3px) solid var(--ed-before-after-focus-color, var(--focus-color, #005fcc)); outline-offset: calc(-1 * var(--ed-before-after-focus-width, 3px)); }\n & .ed-before-after__dock { display: grid; gap: .5rem; min-inline-size: 0; padding-block-start: .5rem; }\n & .ed-before-after__label-dock { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(10rem, 100%), 1fr)); gap: .5rem; min-inline-size: 0; }\n & .ed-before-after__control-dock { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .5rem; min-inline-size: 0; }\n & .ed-before-after__dock .ci-before-after-label { position: static; transform: none; inline-size: auto; max-inline-size: 100%; opacity: 1; font-family: var(--ed-before-after-label-font-family, inherit); font-size: var(--ed-before-after-label-size, var(--text-s, .875rem)); font-weight: var(--ed-before-after-label-weight, 600); color: var(--ed-before-after-label-color, #fff); background: var(--ed-before-after-label-bg, #222); padding: var(--ed-before-after-label-padding, .35em .7em); border-radius: var(--ed-before-after-label-radius, var(--ed-before-after-radius, var(--radius, .25rem))); }\n & .ed-before-after__dock .ci-before-after-zoom-controls,\n & .ed-before-after__dock .ci-before-after-fullscreen-btn,\n & .ed-before-after__dock .ed-before-after__pan-controls { position: static; inset: auto; transform: none; max-inline-size: 100%; flex-wrap: wrap; background: var(--ed-before-after-controls-bg, #fff); color: var(--ed-before-after-controls-color, #222); border-radius: var(--ed-before-after-controls-radius, var(--ed-before-after-radius, var(--radius, .5rem))); box-shadow: var(--ed-before-after-controls-shadow, none); }\n & .ed-before-after__dock .ci-before-after-zoom-controls button { flex: 0 0 var(--_ed-ba-button); color: var(--ed-before-after-controls-color, #222); }\n & .ed-before-after__dock .ci-before-after-fullscreen-btn:hover { background: linear-gradient(var(--ed-before-after-controls-hover-bg, rgb(0 0 0 / .08)) 0 0) var(--ed-before-after-controls-bg, #fff); }\n & .ed-before-after__dock[hidden], & .ed-before-after__label-dock[hidden], & .ed-before-after__control-dock[hidden], & .ed-before-after__pan-controls[hidden] { display: none; }\n @media (forced-colors: active) {\n & .ci-before-after-handle-line { background: CanvasText; }\n & .ci-before-after-handle-grip { border: 2px solid ButtonText; }\n & .ci-before-after-handle:focus-visible .ci-before-after-handle-grip { outline-color: Highlight; }\n }",
"readonly": false
},
"r3ohlh2": {
"type": "class",
"selector": ".ed-before-after__fallback",
"collection": "default",
"css": "",
"readonly": false
},
"kl484w1": {
"type": "class",
"selector": ".ed-before-after__figure",
"collection": "default",
"css": "",
"readonly": false
},
"ktw39ju": {
"type": "class",
"selector": ".ed-before-after__caption",
"collection": "default",
"css": "",
"readonly": false
},
"djm3wvy": {
"type": "class",
"selector": ".ed-before-after__mount",
"collection": "default",
"css": "",
"readonly": false
}
},
"components": {
"119": {
"id": 119,
"legacyId": "",
"name": "ED Before / After Image",
"key": "EdBeforeAfter",
"blocks": [
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "ED Before / After Image"
},
"script": {
"code": "aWYoZ2xvYmFsVGhpc1tTeW1ib2wuZm9yKCJlZC5iZWZvcmUtYWZ0ZXIudjEiKV0pe2dsb2JhbFRoaXNbU3ltYm9sLmZvcigiZWQuYmVmb3JlLWFmdGVyLnYxIildLnNjYW4oKTt9ZWxzZXsKLyohIEV0Y2hEZXZlbG9wZXIgQmVmb3JlIC8gQWZ0ZXIgd3JhcHBlciAxLjAuMC1iZXRhLjMKQ29weXJpZ2h0IDIwMjYgVG9tIENobWllbCwgaHR0cHM6Ly9ldGNoZGV2ZWxvcGVyLmNvbQpTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogRlNMLTEuMS1NSVQgKGh0dHBzOi8vZXRjaGRldmVsb3Blci5jb20vbGljZW5zZS8pCkJ1bmRsZWQgdGhpcmQtcGFydHkgY29kZToKQGNsb3VkaW1hZ2UvYmVmb3JlLWFmdGVyIDEuMC40IOKAlCBTY2FsZWZsZXgKaHR0cHM6Ly9naXRodWIuY29tL3NjYWxlZmxleC9jbG91ZGltYWdlLWJlZm9yZS1hZnRlcgpodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9AY2xvdWRpbWFnZS9iZWZvcmUtYWZ0ZXIKCk1JVCBMaWNlbnNlCgpDb3B5cmlnaHQgKGMpIDIwMjQgU2NhbGVmbGV4CgpQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5Cm9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0byBkZWFsCmluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMKdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbApjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKClRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbApjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLgoKVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRQpBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sCk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFClNPRlRXQVJFLgoKRXRjaERldmVsb3BlciBhcHBsaWVzIGEgdmVyc2lvbi1waW5uZWQgYWNjZXNzaWJpbGl0eSBwYXRjaCB0byB0aGUgYnVuZGxlZCB2ZW5kb3IgSmF2YVNjcmlwdDogY2xpY2sgYWx0ZXJuYXRpdmVzLCBnZXN0dXJlIGNsaWNrIHN1cHByZXNzaW9uLCBwdWJsaWMgcGFuL2NhbmNlbCBob29rcywgcmVwZWF0YWJsZSBlbnRyYW5jZSBhbmltYXRpb24gYW5kIGEgY29tcG9uZW50LWxldmVsIG5hdGl2ZSBmdWxsc2NyZWVuIHRhcmdldC4KKi8KInVzZSBzdHJpY3QiOygoKT0+e3ZhciBTZT1bImRyYWciLCJob3ZlciIsImNsaWNrIl0sTWU9WyJob3Jpem9udGFsIiwidmVydGljYWwiXSxJZT1bImxpZ2h0IiwiZGFyayJdLFRlPVsiYXJyb3dzIiwiY2lyY2xlIiwibGluZSJdLFplPVsidG9wIiwiYm90dG9tIl0sUmU9WyJ0b3AtbGVmdCIsInRvcC1jZW50ZXIiLCJ0b3AtcmlnaHQiLCJib3R0b20tbGVmdCIsImJvdHRvbS1jZW50ZXIiLCJib3R0b20tcmlnaHQiXSx5PXtiZWZvcmVBbHQ6IkJlZm9yZSIsYWZ0ZXJBbHQ6IkFmdGVyIixtb2RlOiJkcmFnIixvcmllbnRhdGlvbjoiaG9yaXpvbnRhbCIsaW5pdGlhbFBvc2l0aW9uOjUwLHpvb206ITEsem9vbU1heDo0LHpvb21NaW46MSx0aGVtZToibGlnaHQiLGhhbmRsZVN0eWxlOiJhcnJvd3MiLGxhYmVsUG9zaXRpb246InRvcCIsYW5pbWF0ZU9uY2U6ITAsZnVsbHNjcmVlbkJ1dHRvbjohMCxsYXp5TG9hZDohMCx6b29tQ29udHJvbHM6ITAsem9vbUNvbnRyb2xzUG9zaXRpb246ImJvdHRvbS1yaWdodCIsc2Nyb2xsSGludDohMCxrZXlib2FyZFN0ZXA6MSxrZXlib2FyZExhcmdlU3RlcDoxMH07ZnVuY3Rpb24gZGUoaSl7bGV0IGU9aS5sYWJlbHMsdD0hMCxvPSJCZWZvcmUiLG49IkFmdGVyIjtlPT09ITE/dD0hMTp0eXBlb2YgZT09Im9iamVjdCImJihvPWUuYmVmb3JlPz8iQmVmb3JlIixuPWUuYWZ0ZXI/PyJBZnRlciIpO2xldCByPWkuYW5pbWF0ZSxzPSExLGg9ODAwLGY9MCxhPSJlYXNlLW91dCI7cj09PSEwP3M9ITA6dHlwZW9mIHI9PSJvYmplY3QiJiYocz0hMCxoPU1hdGgubWF4KDAsci5kdXJhdGlvbj8/ODAwKSxmPU1hdGgubWF4KDAsci5kZWxheT8/MCksYT1yLmVhc2luZz8/ImVhc2Utb3V0Iik7bGV0IGw9aS56b29tPz95Lnpvb207cmV0dXJue2JlZm9yZVNyYzppLmJlZm9yZVNyYyxhZnRlclNyYzppLmFmdGVyU3JjLGJlZm9yZUFsdDppLmJlZm9yZUFsdD8/eS5iZWZvcmVBbHQsYWZ0ZXJBbHQ6aS5hZnRlckFsdD8/eS5hZnRlckFsdCxtb2RlOlooaS5tb2RlLFNlLHkubW9kZSwibW9kZSIpLG9yaWVudGF0aW9uOlooaS5vcmllbnRhdGlvbixNZSx5Lm9yaWVudGF0aW9uLCJvcmllbnRhdGlvbiIpLGluaXRpYWxQb3NpdGlvbjpCZShpLmluaXRpYWxQb3NpdGlvbj8/eS5pbml0aWFsUG9zaXRpb24pLHpvb206bCx6b29tTWF4Ok1hdGgubWF4KDEsaS56b29tTWF4Pz95Lnpvb21NYXgpLHpvb21NaW46TWF0aC5tYXgoMSxNYXRoLm1pbihpLnpvb21NaW4/P3kuem9vbU1pbixpLnpvb21NYXg/P3kuem9vbU1heCkpLHRoZW1lOlooaS50aGVtZSxJZSx5LnRoZW1lLCJ0aGVtZSIpLGhhbmRsZVN0eWxlOlooaS5oYW5kbGVTdHlsZSxUZSx5LmhhbmRsZVN0eWxlLCJoYW5kbGVTdHlsZSIpLGxhYmVsc0VuYWJsZWQ6dCxsYWJlbEJlZm9yZTpvLGxhYmVsQWZ0ZXI6bixsYWJlbFBvc2l0aW9uOlooaS5sYWJlbFBvc2l0aW9uLFplLHkubGFiZWxQb3NpdGlvbiwibGFiZWxQb3NpdGlvbiIpLGFuaW1hdGVFbmFibGVkOnMsYW5pbWF0ZUR1cmF0aW9uOmgsYW5pbWF0ZURlbGF5OmYsYW5pbWF0ZUVhc2luZzphLGFuaW1hdGVPbmNlOmkuYW5pbWF0ZU9uY2U/P3kuYW5pbWF0ZU9uY2UsZnVsbHNjcmVlbkJ1dHRvbjppLmZ1bGxzY3JlZW5CdXR0b24/P3kuZnVsbHNjcmVlbkJ1dHRvbixsYXp5TG9hZDppLmxhenlMb2FkPz95LmxhenlMb2FkLHpvb21Db250cm9sczppLnpvb21Db250cm9scz8/KGw/eS56b29tQ29udHJvbHM6ITEpLHpvb21Db250cm9sc1Bvc2l0aW9uOlooaS56b29tQ29udHJvbHNQb3NpdGlvbixSZSx5Lnpvb21Db250cm9sc1Bvc2l0aW9uLCJ6b29tQ29udHJvbHNQb3NpdGlvbiIpLHNjcm9sbEhpbnQ6aS5zY3JvbGxIaW50Pz8obD95LnNjcm9sbEhpbnQ6ITEpLGtleWJvYXJkU3RlcDpNYXRoLm1heCguNSxpLmtleWJvYXJkU3RlcD8/eS5rZXlib2FyZFN0ZXApLGtleWJvYXJkTGFyZ2VTdGVwOk1hdGgubWF4KDEsaS5rZXlib2FyZExhcmdlU3RlcD8/eS5rZXlib2FyZExhcmdlU3RlcCksb25TbGlkZTppLm9uU2xpZGUsb25ab29tOmkub25ab29tLG9uRnVsbHNjcmVlbkNoYW5nZTppLm9uRnVsbHNjcmVlbkNoYW5nZSxvblJlYWR5Omkub25SZWFkeSxhc3BlY3RSYXRpbzppLmFzcGVjdFJhdGlvLGNsb3VkaW1hZ2U6aS5jbG91ZGltYWdlfX1mdW5jdGlvbiBaKGksZSx0LG8pe3JldHVybiBpPT09dm9pZCAwP3Q6ZS5pbmNsdWRlcyhpKT9pOihjb25zb2xlLndhcm4oYENJQmVmb3JlQWZ0ZXI6IEludmFsaWQgJHtvfSAiJHtpfSIuIEFsbG93ZWQ6ICR7ZS5qb2luKCIsICIpfS4gVXNpbmcgZGVmYXVsdCAiJHt0fSIuYCksdCl9ZnVuY3Rpb24gQmUoaSl7cmV0dXJuIGlzRmluaXRlKGkpP01hdGgubWF4KDAsTWF0aC5taW4oMTAwLGkpKTo1MH1mdW5jdGlvbiB2KGksZSx0KXtsZXQgbz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KGkpO2lmKGUmJihvLmNsYXNzTmFtZT1lKSx0KWZvcihsZXRbbixyXW9mIE9iamVjdC5lbnRyaWVzKHQpKW8uc2V0QXR0cmlidXRlKG4scik7cmV0dXJuIG99ZnVuY3Rpb24gT2UoaSl7aWYodHlwZW9mIGk9PSJzdHJpbmciKXtsZXQgZT1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGkpO2lmKCFlKXRocm93IG5ldyBFcnJvcihgQ0lCZWZvcmVBZnRlcjogRWxlbWVudCBub3QgZm91bmQgZm9yIHNlbGVjdG9yICIke2l9ImApO3JldHVybiBlfXJldHVybiBpfWZ1bmN0aW9uIERlKCl7cmV0dXJuIHR5cGVvZiB3aW5kb3c8InUiJiZ0eXBlb2YgZG9jdW1lbnQ8InUifWZ1bmN0aW9uIFEoKXtpZighRGUoKSlyZXR1cm4hMTtsZXQgaT1kb2N1bWVudDtyZXR1cm4hIShpLmZ1bGxzY3JlZW5FbmFibGVkfHxpLndlYmtpdEZ1bGxzY3JlZW5FbmFibGVkKX1mdW5jdGlvbiBGZShpKXtsZXQgZT1pO3JldHVybiBlLnJlcXVlc3RGdWxsc2NyZWVuP2UucmVxdWVzdEZ1bGxzY3JlZW4oKTplLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuP2Uud2Via2l0UmVxdWVzdEZ1bGxzY3JlZW4oKTpQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIkZ1bGxzY3JlZW4gQVBJIG5vdCBzdXBwb3J0ZWQiKSl9ZnVuY3Rpb24gbWUoKXtsZXQgaT1kb2N1bWVudDtyZXR1cm4gaS5leGl0RnVsbHNjcmVlbj9pLmV4aXRGdWxsc2NyZWVuKCk6aS53ZWJraXRFeGl0RnVsbHNjcmVlbj9pLndlYmtpdEV4aXRGdWxsc2NyZWVuKCk6UHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCJGdWxsc2NyZWVuIEFQSSBub3Qgc3VwcG9ydGVkIikpfWZ1bmN0aW9uIHVlKCl7bGV0IGk9ZG9jdW1lbnQ7cmV0dXJuIGkuZnVsbHNjcmVlbkVsZW1lbnR8fGkud2Via2l0RnVsbHNjcmVlbkVsZW1lbnR8fG51bGx9dmFyIEU9Y2xhc3N7Y29uc3RydWN0b3IoKXt0aGlzLmNsZWFudXBzPVtdfW9uKGUsdCxvLG4pe2UuYWRkRXZlbnRMaXN0ZW5lcih0LG8sbiksdGhpcy5jbGVhbnVwcy5wdXNoKCgpPT5lLnJlbW92ZUV2ZW50TGlzdGVuZXIodCxvLG4pKX1vblBhc3NpdmUoZSx0LG8pe3RoaXMub24oZSx0LG8se3Bhc3NpdmU6ITB9KX1vbk5vblBhc3NpdmUoZSx0LG8pe3RoaXMub24oZSx0LG8se3Bhc3NpdmU6ITF9KX1kZXN0cm95KCl7Zm9yKGxldCBlIG9mIHRoaXMuY2xlYW51cHMpZSgpO3RoaXMuY2xlYW51cHM9W119fTtmdW5jdGlvbiBIZShpLGUpe3ZhciB0O2xldCBvLG47aWYoInRvdWNoZXMiaW4gaSl7bGV0IHI9aS50b3VjaGVzWzBdfHwoKHQ9aS5jaGFuZ2VkVG91Y2hlcyk9PW51bGw/dm9pZCAwOnRbMF0pO2lmKCFyKXJldHVybnt4OjAseTowfTtvPXIuY2xpZW50WCxuPXIuY2xpZW50WX1lbHNlIG89aS5jbGllbnRYLG49aS5jbGllbnRZO3JldHVybnt4Om8tZS5sZWZ0LHk6bi1lLnRvcH19ZnVuY3Rpb24gaihpLGUsdCl7bGV0e3g6byx5Om59PUhlKGksZSkscj10PT09Imhvcml6b250YWwiP2Uud2lkdGg6ZS5oZWlnaHQ7cmV0dXJuIHI9PT0wPzUwOk1hdGgubWF4KDAsTWF0aC5taW4oMTAwLCh0PT09Imhvcml6b250YWwiP286bikvcioxMDApKX12YXIgJGU9L15bYS16QS1aMC05Xy1dKyQvLGplPS9eW2EtekEtWjAtOS4tXStcLlthLXpBLVpdezIsfSQvLFllPS9edlxkKyQvO2Z1bmN0aW9uIE5lKGkpe2lmKCEkZS50ZXN0KGkudG9rZW4pKXRocm93IG5ldyBFcnJvcihgQ0lCZWZvcmVBZnRlcjogSW52YWxpZCBjbG91ZGltYWdlIHRva2VuICIke2kudG9rZW59Ii4gTXVzdCBtYXRjaCBbYS16QS1aMC05Xy1dK2ApO2lmKGkuZG9tYWluJiYhamUudGVzdChpLmRvbWFpbikpdGhyb3cgbmV3IEVycm9yKGBDSUJlZm9yZUFmdGVyOiBJbnZhbGlkIGNsb3VkaW1hZ2UgZG9tYWluICIke2kuZG9tYWlufSIuYCk7aWYoaS5hcGlWZXJzaW9uJiYhWWUudGVzdChpLmFwaVZlcnNpb24pKXRocm93IG5ldyBFcnJvcihgQ0lCZWZvcmVBZnRlcjogSW52YWxpZCBjbG91ZGltYWdlIGFwaVZlcnNpb24gIiR7aS5hcGlWZXJzaW9ufSIuIE11c3QgYmUgInYiIGZvbGxvd2VkIGJ5IGRpZ2l0cy5gKX1mdW5jdGlvbiBYZShpLGUsdCl7TmUodCk7bGV0e3Rva2VuOm8sYXBpVmVyc2lvbjpuPSJ2NyIsZG9tYWluOnI9ImNsb3VkaW1nLmlvIixsaW1pdEZhY3RvcjpzPTEwMCxwYXJhbXM6aD0iIixkZXZpY2VQaXhlbFJhdGlvTGlzdDpmPVsxLDEuNSwyXX09dCxhPXR5cGVvZiB3aW5kb3c8InUiJiZ3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MSxsPShmLmxlbmd0aD4wP2Y6WzFdKS5yZWR1Y2UoKE0sSSk9Pk1hdGguYWJzKEktYSk8TWF0aC5hYnMoTS1hKT9JOk0pLGI9cz4wP3M6MTAwLGc9ZSpsLHc9TWF0aC5jZWlsKGcvYikqYix4PWBodHRwczovLyR7b30uJHtyfS8ke259YCx6PWg/YD8ke2h9Jnc9JHt3fWA6YD93PSR7d31gO3JldHVybiBpLnN0YXJ0c1dpdGgoImh0dHA6Ly8iKXx8aS5zdGFydHNXaXRoKCJodHRwczovLyIpP2Ake3h9LyR7aX0ke3p9YDpgJHt4fS8ke2l9JHt6fWB9ZnVuY3Rpb24gZWUoaSxlLHQsbyl7bGV0IG49ZTtvJiZvLmxldmVsPjEmJih0PT09Imhvcml6b250YWwiP249ZS9vLmxldmVsLW8ucGFuWCoxMDAvKG8ubGV2ZWwqby5jb250YWluZXJXaWR0aCk6bj1lL28ubGV2ZWwtby5wYW5ZKjEwMC8oby5sZXZlbCpvLmNvbnRhaW5lckhlaWdodCksbj1NYXRoLm1heCgwLE1hdGgubWluKDEwMCxuKSkpO2xldCByPXQ9PT0iaG9yaXpvbnRhbCI/YGluc2V0KDAgMCAwICR7bn0lKWA6YGluc2V0KCR7bn0lIDAgMCAwKWA7aS5zdHlsZS5jbGlwUGF0aD1yLGkuc3R5bGUuc2V0UHJvcGVydHkoIi13ZWJraXQtY2xpcC1wYXRoIixyKX1mdW5jdGlvbiBfZShpLGUsdCl7dD09PSJob3Jpem9udGFsIj8oaS5zdHlsZS5sZWZ0PWAke2V9JWAsaS5zdHlsZS50b3A9IiIpOihpLnN0eWxlLnRvcD1gJHtlfSVgLGkuc3R5bGUubGVmdD0iIil9ZnVuY3Rpb24gYmUoaSl7cmV0dXJuIGlzRmluaXRlKGkpP01hdGgubWF4KDAsTWF0aC5taW4oMTAwLGkpKTo1MH12YXIgV2U9JzxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJtMTUgMTgtNi02IDYtNiIvPjwvc3ZnPicscWU9JzxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJtOSAxOCA2LTYtNi02Ii8+PC9zdmc+JyxVZT0nPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Im0xOCAxNS02LTYtNiA2Ii8+PC9zdmc+JyxLZT0nPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Im02IDkgNiA2IDYtNiIvPjwvc3ZnPicsR2U9JzxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWxpbmUgcG9pbnRzPSIxOCA4IDIyIDEyIDE4IDE2Ii8+PHBvbHlsaW5lIHBvaW50cz0iNiA4IDIgMTIgNiAxNiIvPjxsaW5lIHgxPSIyIiB4Mj0iMjIiIHkxPSIxMiIgeTI9IjEyIi8+PC9zdmc+JyxWZT0nPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwb2x5bGluZSBwb2ludHM9IjggMTggMTIgMjIgMTYgMTgiLz48cG9seWxpbmUgcG9pbnRzPSI4IDYgMTIgMiAxNiA2Ii8+PGxpbmUgeDE9IjEyIiB4Mj0iMTIiIHkxPSIyIiB5Mj0iMjIiLz48L3N2Zz4nO2Z1bmN0aW9uIGdlKGksZSx0KXtsZXQgbz12KCJkaXYiLGBjaS1iZWZvcmUtYWZ0ZXItaGFuZGxlIGNpLWJlZm9yZS1hZnRlci1oYW5kbGUtLSR7aX1gLHtyb2xlOiJzbGlkZXIiLCJhcmlhLXZhbHVlbm93IjpTdHJpbmcoTWF0aC5yb3VuZCh0KSksImFyaWEtdmFsdWVtaW4iOiIwIiwiYXJpYS12YWx1ZW1heCI6IjEwMCIsImFyaWEtbGFiZWwiOiJJbWFnZSBjb21wYXJpc29uIHNsaWRlci4gVXNlIGFycm93IGtleXMgdG8gYWRqdXN0IHRoZSBiZWZvcmUgYW5kIGFmdGVyIHNwbGl0IHBvc2l0aW9uLiIsImFyaWEtb3JpZW50YXRpb24iOmUsdGFiaW5kZXg6IjAifSk7c3dpdGNoKGU9PT0iaG9yaXpvbnRhbCI/by5zdHlsZS5sZWZ0PWAke3R9JWA6by5zdHlsZS50b3A9YCR7dH0lYCxpKXtjYXNlImFycm93cyI6SmUobyxlKTticmVhaztjYXNlImNpcmNsZSI6UWUobyxlKTticmVhaztjYXNlImxpbmUiOmV0KG8pO2JyZWFrfXJldHVybiBvfWZ1bmN0aW9uIEplKGksZSl7bGV0IHQ9digiZGl2IiwiY2ktYmVmb3JlLWFmdGVyLWhhbmRsZS1saW5lIiksbz12KCJkaXYiLCJjaS1iZWZvcmUtYWZ0ZXItaGFuZGxlLWdyaXAiKSxuPXYoImRpdiIsImNpLWJlZm9yZS1hZnRlci1oYW5kbGUtbGluZSIpO2U9PT0iaG9yaXpvbnRhbCI/by5pbm5lckhUTUw9V2UrcWU6by5pbm5lckhUTUw9VWUrS2UsaS5hcHBlbmQodCxvLG4pfWZ1bmN0aW9uIFFlKGksZSl7bGV0IHQ9digiZGl2IiwiY2ktYmVmb3JlLWFmdGVyLWhhbmRsZS1ncmlwIik7ZT09PSJob3Jpem9udGFsIj90LmlubmVySFRNTD1HZTp0LmlubmVySFRNTD1WZSxpLmFwcGVuZCh0KX1mdW5jdGlvbiBldChpKXtsZXQgZT12KCJkaXYiLCJjaS1iZWZvcmUtYWZ0ZXItaGFuZGxlLWxpbmUiKSx0PXYoImRpdiIsImNpLWJlZm9yZS1hZnRlci1oYW5kbGUtZ3JpcCBjaS1iZWZvcmUtYWZ0ZXItaGFuZGxlLWdyaXAtLXBpbGwiKSxvPXYoImRpdiIsImNpLWJlZm9yZS1hZnRlci1oYW5kbGUtbGluZSIpO2kuYXBwZW5kKGUsdCxvKX12YXIgWT1jbGFzc3tjb25zdHJ1Y3RvcihlLHQsbyxuLHIpe3RoaXMuY29udGFpbmVyPWUsdGhpcy5oYW5kbGU9dCx0aGlzLm1vZGU9byx0aGlzLm9yaWVudGF0aW9uPW4sdGhpcy5jYWxsYmFja3M9cix0aGlzLmV2ZW50cz1uZXcgRSx0aGlzLmNvbnRhaW5lclJlY3Q9bnVsbCx0aGlzLnJhZklkPW51bGwsdGhpcy5wZW5kaW5nUG9zaXRpb249bnVsbCx0aGlzLmFib3J0Q29udHJvbGxlcj1udWxsLHRoaXMuYmluZCgpfWJpbmQoKXtzd2l0Y2godGhpcy5tb2RlKXtjYXNlImRyYWciOnRoaXMuYmluZERyYWcoKTticmVhaztjYXNlImhvdmVyIjp0aGlzLmJpbmRIb3ZlcigpO2JyZWFrO2Nhc2UiY2xpY2siOnRoaXMuYmluZENsaWNrKCk7YnJlYWt9fWJpbmREcmFnKCl7dGhpcy5iaW5kQ2xpY2soKSx0aGlzLmV2ZW50cy5vbih0aGlzLmhhbmRsZSwibW91c2Vkb3duIixlPT57ZS5wcmV2ZW50RGVmYXVsdCgpLHRoaXMuc3RhcnREcmFnKCl9KSx0aGlzLmV2ZW50cy5vbih0aGlzLmhhbmRsZSwidG91Y2hzdGFydCIsZT0+e2UucHJldmVudERlZmF1bHQoKSx0aGlzLmhhbmRsZS5mb2N1cygpLHRoaXMuc3RhcnRUb3VjaERyYWcoKX0se3Bhc3NpdmU6ITF9KX1zdGFydERyYWcoKXt0aGlzLmNsZWFudXBXaW5kb3dMaXN0ZW5lcnMoKSx0aGlzLmFib3J0Q29udHJvbGxlcj1uZXcgQWJvcnRDb250cm9sbGVyO2xldCBlPXRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbDt0aGlzLmNvbnRhaW5lclJlY3Q9dGhpcy5jb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksdGhpcy5jYWxsYmFja3Mub25EcmFnU3RhcnQoKTtsZXQgdD1uPT57aWYoIXRoaXMuY29udGFpbmVyUmVjdClyZXR1cm47dGhpcy5jb250YWluZXIuX19lZEJlZm9yZUFmdGVyU3VwcHJlc3NDbGljaz0hMDtsZXQgcj1qKG4sdGhpcy5jb250YWluZXJSZWN0LHRoaXMub3JpZW50YXRpb24pO3RoaXMuc2NoZWR1bGVQb3NpdGlvblVwZGF0ZShyKX0sbz0oKT0+e3RoaXMuZmx1c2hQb3NpdGlvblVwZGF0ZSgpLHRoaXMuY2FsbGJhY2tzLm9uRHJhZ0VuZCgpLHRoaXMuY29udGFpbmVyUmVjdD1udWxsLHRoaXMuY2xlYW51cFdpbmRvd0xpc3RlbmVycygpfTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigibW91c2Vtb3ZlIix0LHtzaWduYWw6ZX0pLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJtb3VzZXVwIixvLHtzaWduYWw6ZX0pfXN0YXJ0VG91Y2hEcmFnKCl7dGhpcy5jbGVhbnVwV2luZG93TGlzdGVuZXJzKCksdGhpcy5hYm9ydENvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcjtsZXQgZT10aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWw7dGhpcy5jb250YWluZXJSZWN0PXRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLHRoaXMuY2FsbGJhY2tzLm9uRHJhZ1N0YXJ0KCk7bGV0IHQ9bj0+e2lmKCF0aGlzLmNvbnRhaW5lclJlY3R8fG4udG91Y2hlcy5sZW5ndGghPT0xKXJldHVybjtuLnByZXZlbnREZWZhdWx0KCksdGhpcy5jb250YWluZXIuX19lZEJlZm9yZUFmdGVyU3VwcHJlc3NDbGljaz0hMDtsZXQgcj1qKG4sdGhpcy5jb250YWluZXJSZWN0LHRoaXMub3JpZW50YXRpb24pO3RoaXMuc2NoZWR1bGVQb3NpdGlvblVwZGF0ZShyKX0sbz0oKT0+e3RoaXMuZmx1c2hQb3NpdGlvblVwZGF0ZSgpLHRoaXMuY2FsbGJhY2tzLm9uRHJhZ0VuZCgpLHRoaXMuY29udGFpbmVyUmVjdD1udWxsLHRoaXMuY2xlYW51cFdpbmRvd0xpc3RlbmVycygpfTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigidG91Y2htb3ZlIix0LHtwYXNzaXZlOiExLHNpZ25hbDplfSksd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoZW5kIixvLHtzaWduYWw6ZX0pLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ0b3VjaGNhbmNlbCIsbyx7c2lnbmFsOmV9KX1zY2hlZHVsZVBvc2l0aW9uVXBkYXRlKGUpe3RoaXMucGVuZGluZ1Bvc2l0aW9uPWUsdGhpcy5yYWZJZD09PW51bGwmJih0aGlzLnJhZklkPXJlcXVlc3RBbmltYXRpb25GcmFtZSgoKT0+e3RoaXMucmFmSWQ9bnVsbCx0aGlzLnBlbmRpbmdQb3NpdGlvbiE9PW51bGwmJih0aGlzLmNhbGxiYWNrcy5vblBvc2l0aW9uQ2hhbmdlKHRoaXMucGVuZGluZ1Bvc2l0aW9uKSx0aGlzLnBlbmRpbmdQb3NpdGlvbj1udWxsKX0pKX1mbHVzaFBvc2l0aW9uVXBkYXRlKCl7dGhpcy5yYWZJZCE9PW51bGwmJihjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJhZklkKSx0aGlzLnJhZklkPW51bGwpLHRoaXMucGVuZGluZ1Bvc2l0aW9uIT09bnVsbCYmKHRoaXMuY2FsbGJhY2tzLm9uUG9zaXRpb25DaGFuZ2UodGhpcy5wZW5kaW5nUG9zaXRpb24pLHRoaXMucGVuZGluZ1Bvc2l0aW9uPW51bGwpfWNsZWFudXBXaW5kb3dMaXN0ZW5lcnMoKXt0aGlzLmFib3J0Q29udHJvbGxlciYmKHRoaXMuYWJvcnRDb250cm9sbGVyLmFib3J0KCksdGhpcy5hYm9ydENvbnRyb2xsZXI9bnVsbCl9YmluZEhvdmVyKCl7dGhpcy5ldmVudHMub24odGhpcy5jb250YWluZXIsIm1vdXNlbW92ZSIsZT0+e2xldCB0PXRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLG89aihlLHQsdGhpcy5vcmllbnRhdGlvbik7dGhpcy5zY2hlZHVsZVBvc2l0aW9uVXBkYXRlKG8pfSl9YmluZENsaWNrKCl7bGV0IGU9KCk9Pnt0aGlzLmNvbnRhaW5lci5fX2VkQmVmb3JlQWZ0ZXJTdXBwcmVzc0NsaWNrPSExfTt0aGlzLmV2ZW50cy5vbih0aGlzLmNvbnRhaW5lciwibW91c2Vkb3duIixlKSx0aGlzLmV2ZW50cy5vbih0aGlzLmNvbnRhaW5lciwidG91Y2hzdGFydCIsZSksdGhpcy5ldmVudHMub24odGhpcy5jb250YWluZXIsImNsaWNrIix0PT57aWYodGhpcy5jb250YWluZXIuX19lZEJlZm9yZUFmdGVyU3VwcHJlc3NDbGljayl7dGhpcy5jb250YWluZXIuX19lZEJlZm9yZUFmdGVyU3VwcHJlc3NDbGljaz0hMTtyZXR1cm59aWYodGhpcy5oYW5kbGUuY29udGFpbnModC50YXJnZXQpfHx0LnRhcmdldC5jbG9zZXN0KCJidXR0b24iKSlyZXR1cm47bGV0IG89dGhpcy5jb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksbj1qKHQsbyx0aGlzLm9yaWVudGF0aW9uKTt0aGlzLmNhbGxiYWNrcy5vblBvc2l0aW9uQ2hhbmdlKG4pfSl9dXBkYXRlTW9kZShlKXt0aGlzLmV2ZW50cy5kZXN0cm95KCksdGhpcy5jbGVhbnVwV2luZG93TGlzdGVuZXJzKCksdGhpcy5mbHVzaFBvc2l0aW9uVXBkYXRlKCksdGhpcy5tb2RlPWUsdGhpcy5iaW5kKCl9dXBkYXRlT3JpZW50YXRpb24oZSl7dGhpcy5vcmllbnRhdGlvbj1lfWRlc3Ryb3koKXt0aGlzLmNsZWFudXBXaW5kb3dMaXN0ZW5lcnMoKSx0aGlzLnJhZklkIT09bnVsbCYmKGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmFmSWQpLHRoaXMucmFmSWQ9bnVsbCksdGhpcy5wZW5kaW5nUG9zaXRpb249bnVsbCx0aGlzLmV2ZW50cy5kZXN0cm95KCksdGhpcy5jb250YWluZXJSZWN0PW51bGx9fSx0ZT1jbGFzc3tjb25zdHJ1Y3RvcihlLHQsbyxuLHIpe3RoaXMudmlld3BvcnQ9ZSx0aGlzLmNvbnRhaW5lcj10LHRoaXMuY29uZmlnPW8sdGhpcy5vblpvb21DaGFuZ2U9bix0aGlzLnpvb21MZXZlbD0xLHRoaXMucGFuWD0wLHRoaXMucGFuWT0wLHRoaXMuY29udGFpbmVyV2lkdGg9MCx0aGlzLmNvbnRhaW5lckhlaWdodD0wLHRoaXMudHJhbnNpdGlvbmluZz0hMSx0aGlzLnRyYW5zaXRpb25FbmRDbGVhbnVwPW51bGwsdGhpcy5yZXNpemVPYnNlcnZlcj1udWxsLHRoaXMub25UcmFuc2Zvcm1DaGFuZ2U9cix0aGlzLnVwZGF0ZUNvbnRhaW5lclNpemUoKSx0aGlzLm9ic2VydmVSZXNpemUoKX1vYnNlcnZlUmVzaXplKCl7dHlwZW9mIFJlc2l6ZU9ic2VydmVyPiJ1Inx8KHRoaXMucmVzaXplT2JzZXJ2ZXI9bmV3IFJlc2l6ZU9ic2VydmVyKGU9Pntmb3IobGV0IHQgb2YgZSl7bGV0e3dpZHRoOm8saGVpZ2h0Om59PXQuY29udGVudFJlY3Q7dGhpcy5jb250YWluZXJXaWR0aD1vLHRoaXMuY29udGFpbmVySGVpZ2h0PW59fSksdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMuY29udGFpbmVyKSl9Z2V0Wm9vbSgpe3JldHVybiB0aGlzLnpvb21MZXZlbH1nZXRDb250YWluZXJTaXplKCl7cmV0dXJue3dpZHRoOnRoaXMuY29udGFpbmVyV2lkdGgsaGVpZ2h0OnRoaXMuY29udGFpbmVySGVpZ2h0fX1zZXRab29tKGUsdCxvKXt2YXIgbjtsZXQgcj1NYXRoLm1heCh0aGlzLmNvbmZpZy56b29tTWluLE1hdGgubWluKHRoaXMuY29uZmlnLnpvb21NYXgsZSkpO2lmKHI9PT10aGlzLnpvb21MZXZlbClyZXR1cm47bGV0IHM9dGhpcy56b29tTGV2ZWw7dGhpcy56b29tTGV2ZWw9cix0IT09dm9pZCAwJiZvIT09dm9pZCAwJiYodGhpcy5wYW5YPXQtKHQtdGhpcy5wYW5YKSooci9zKSx0aGlzLnBhblk9by0oby10aGlzLnBhblkpKihyL3MpKSx0aGlzLmNsYW1wUGFuKCksdGhpcy5hcHBseVRyYW5zZm9ybSghMCksKG49dGhpcy5vblpvb21DaGFuZ2UpPT1udWxsfHxuLmNhbGwodGhpcyx0aGlzLnpvb21MZXZlbCl9em9vbUluKCl7dGhpcy5zZXRab29tKHRoaXMuem9vbUxldmVsKjEuNSx0aGlzLmNvbnRhaW5lcldpZHRoLzIsdGhpcy5jb250YWluZXJIZWlnaHQvMil9em9vbU91dCgpe3RoaXMuc2V0Wm9vbSh0aGlzLnpvb21MZXZlbC8xLjUsdGhpcy5jb250YWluZXJXaWR0aC8yLHRoaXMuY29udGFpbmVySGVpZ2h0LzIpfXJlc2V0Wm9vbSgpe3ZhciBlO3RoaXMuem9vbUxldmVsPU1hdGgubWF4KDEsdGhpcy5jb25maWcuem9vbU1pbiksdGhpcy5wYW5YPTAsdGhpcy5wYW5ZPTAsdGhpcy5hcHBseVRyYW5zZm9ybSghMCksKGU9dGhpcy5vblpvb21DaGFuZ2UpPT1udWxsfHxlLmNhbGwodGhpcyx0aGlzLnpvb21MZXZlbCl9Z2V0UGFuKCl7cmV0dXJue3g6dGhpcy5wYW5YLHk6dGhpcy5wYW5ZfX1zZXRQYW4oZSx0KXt0aGlzLnBhblg9ZSx0aGlzLnBhblk9dCx0aGlzLmNsYW1wUGFuKCksdGhpcy5hcHBseVRyYW5zZm9ybSghMSl9cGFuKGUsdCl7dGhpcy56b29tTGV2ZWw8PTF8fCh0aGlzLnBhblgrPWUsdGhpcy5wYW5ZKz10LHRoaXMuY2xhbXBQYW4oKSx0aGlzLmFwcGx5VHJhbnNmb3JtKCExKSl9aGFuZGxlV2hlZWwoZSl7aWYoIWUuY3RybEtleSYmIWUubWV0YUtleSlyZXR1cm47ZS5wcmV2ZW50RGVmYXVsdCgpO2xldCB0PXRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLG89ZS5jbGllbnRYLXQubGVmdCxuPWUuY2xpZW50WS10LnRvcCxyPWUuZGVsdGFZPjA/Ljk6MS4xO3RoaXMuc2V0Wm9vbSh0aGlzLnpvb21MZXZlbCpyLG8sbil9dG9nZ2xlWm9vbShlLHQpe2xldCBvPU1hdGgubWF4KDEsdGhpcy5jb25maWcuem9vbU1pbik7dGhpcy56b29tTGV2ZWw+bz90aGlzLnJlc2V0Wm9vbSgpOnRoaXMuc2V0Wm9vbShNYXRoLm1heCgyLG8qMS41KSxlLHQpfXVwZGF0ZUNvbmZpZyhlKXt2YXIgdDt0aGlzLmNvbmZpZz1lO2xldCBvPU1hdGgubWF4KGUuem9vbU1pbixNYXRoLm1pbihlLnpvb21NYXgsdGhpcy56b29tTGV2ZWwpKTtvIT09dGhpcy56b29tTGV2ZWwmJih0aGlzLnpvb21MZXZlbD1vLCh0PXRoaXMub25ab29tQ2hhbmdlKT09bnVsbHx8dC5jYWxsKHRoaXMsdGhpcy56b29tTGV2ZWwpKSx0aGlzLmNsYW1wUGFuKCksdGhpcy5hcHBseVRyYW5zZm9ybSghMSl9dXBkYXRlQ29udGFpbmVyU2l6ZSgpe2xldCBlPXRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO3RoaXMuY29udGFpbmVyV2lkdGg9ZS53aWR0aCx0aGlzLmNvbnRhaW5lckhlaWdodD1lLmhlaWdodH1jbGFtcFBhbigpe2lmKHRoaXMuem9vbUxldmVsPD0xKXt0aGlzLnBhblg9MCx0aGlzLnBhblk9MDtyZXR1cm59bGV0IGU9dGhpcy5jb250YWluZXJXaWR0aCoodGhpcy56b29tTGV2ZWwtMSksdD10aGlzLmNvbnRhaW5lckhlaWdodCoodGhpcy56b29tTGV2ZWwtMSk7dGhpcy5wYW5YPU1hdGgubWF4KC1lLE1hdGgubWluKDAsdGhpcy5wYW5YKSksdGhpcy5wYW5ZPU1hdGgubWF4KC10LE1hdGgubWluKDAsdGhpcy5wYW5ZKSl9YXBwbHlUcmFuc2Zvcm0oZSl7dmFyIHQ7aWYodGhpcy50cmFuc2l0aW9uRW5kQ2xlYW51cCYmKHRoaXMudHJhbnNpdGlvbkVuZENsZWFudXAoKSx0aGlzLnRyYW5zaXRpb25FbmRDbGVhbnVwPW51bGwpLGUpe3RoaXMudmlld3BvcnQuc3R5bGUudHJhbnNpdGlvbj0idHJhbnNmb3JtIDMwMG1zIGVhc2UiLHRoaXMudHJhbnNpdGlvbmluZz0hMDtsZXQgbz1uPT57bi50YXJnZXQ9PT10aGlzLnZpZXdwb3J0JiYodGhpcy52aWV3cG9ydC5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMudHJhbnNpdGlvbmluZz0hMSx0aGlzLnRyYW5zaXRpb25FbmRDbGVhbnVwPW51bGwsdGhpcy52aWV3cG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCJ0cmFuc2l0aW9uZW5kIixvKSl9O3RoaXMudmlld3BvcnQuYWRkRXZlbnRMaXN0ZW5lcigidHJhbnNpdGlvbmVuZCIsbyksdGhpcy50cmFuc2l0aW9uRW5kQ2xlYW51cD0oKT0+e3RoaXMudmlld3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigidHJhbnNpdGlvbmVuZCIsbyksdGhpcy52aWV3cG9ydC5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMudHJhbnNpdGlvbmluZz0hMX19ZWxzZSB0aGlzLnRyYW5zaXRpb25pbmd8fCh0aGlzLnZpZXdwb3J0LnN0eWxlLnRyYW5zaXRpb249IiIpO3RoaXMudmlld3BvcnQuc3R5bGUudHJhbnNmb3JtPWBzY2FsZSgke3RoaXMuem9vbUxldmVsfSkgdHJhbnNsYXRlKCR7dGhpcy5wYW5YL3RoaXMuem9vbUxldmVsfXB4LCAke3RoaXMucGFuWS90aGlzLnpvb21MZXZlbH1weClgLCh0PXRoaXMub25UcmFuc2Zvcm1DaGFuZ2UpPT1udWxsfHx0LmNhbGwodGhpcyl9ZGVzdHJveSgpe3ZhciBlO3RoaXMudHJhbnNpdGlvbkVuZENsZWFudXAmJih0aGlzLnRyYW5zaXRpb25FbmRDbGVhbnVwKCksdGhpcy50cmFuc2l0aW9uRW5kQ2xlYW51cD1udWxsKSx0aGlzLnZpZXdwb3J0LnN0eWxlLnRyYW5zZm9ybT0iIix0aGlzLnZpZXdwb3J0LnN0eWxlLnRyYW5zaXRpb249IiIsKGU9dGhpcy5yZXNpemVPYnNlcnZlcik9PW51bGx8fGUuZGlzY29ubmVjdCgpLHRoaXMucmVzaXplT2JzZXJ2ZXI9bnVsbH19LHR0PTMsTj1jbGFzc3tjb25zdHJ1Y3RvcihlLHQsbyxuKXt0aGlzLmNvbnRhaW5lcj1lLHRoaXMuaGFuZGxlPXQsdGhpcy56b29tUGFuPW8sdGhpcy5zY3JvbGxIaW50Q2FsbGJhY2s9bix0aGlzLmV2ZW50cz1uZXcgRSx0aGlzLmlzUGFubmluZz0hMSx0aGlzLmxhc3RQYW5YPTAsdGhpcy5sYXN0UGFuWT0wLHRoaXMuaW5pdGlhbFBpbmNoRGlzdGFuY2U9MCx0aGlzLmluaXRpYWxQaW5jaFpvb209MSx0aGlzLmFib3J0Q29udHJvbGxlcj1udWxsLHRoaXMuYmluZCgpfWJpbmQoKXt0aGlzLmV2ZW50cy5vbk5vblBhc3NpdmUodGhpcy5jb250YWluZXIsIndoZWVsIixlPT57dmFyIHQ7ZS5jdHJsS2V5fHxlLm1ldGFLZXk/dGhpcy56b29tUGFuLmhhbmRsZVdoZWVsKGUpOnRoaXMuem9vbVBhbi5nZXRab29tKCk+MXx8KHQ9dGhpcy5zY3JvbGxIaW50Q2FsbGJhY2spPT1udWxsfHx0LmNhbGwodGhpcyl9KSx0aGlzLmV2ZW50cy5vbih0aGlzLmNvbnRhaW5lciwiZGJsY2xpY2siLGU9PntpZih0aGlzLmhhbmRsZS5jb250YWlucyhlLnRhcmdldCkpcmV0dXJuO2xldCB0PXRoaXMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO3RoaXMuem9vbVBhbi50b2dnbGVab29tKGUuY2xpZW50WC10LmxlZnQsZS5jbGllbnRZLXQudG9wKX0pLHRoaXMuZXZlbnRzLm9uKHRoaXMuY29udGFpbmVyLCJtb3VzZWRvd24iLGU9Pnt0aGlzLmhhbmRsZS5jb250YWlucyhlLnRhcmdldCl8fHRoaXMuem9vbVBhbi5nZXRab29tKCk8PTF8fChlLnByZXZlbnREZWZhdWx0KCksdGhpcy5zdGFydFBhbihlLmNsaWVudFgsZS5jbGllbnRZKSl9KSx0aGlzLmV2ZW50cy5vbih0aGlzLmNvbnRhaW5lciwidG91Y2hzdGFydCIsZT0+e3RoaXMuaGFuZGxlLmNvbnRhaW5zKGUudGFyZ2V0KXx8KGUudG91Y2hlcy5sZW5ndGg9PT0yPyhlLnByZXZlbnREZWZhdWx0KCksdGhpcy5zdGFydFBpbmNoKGUpKTplLnRvdWNoZXMubGVuZ3RoPT09MSYmdGhpcy56b29tUGFuLmdldFpvb20oKT4xJiYoZS5wcmV2ZW50RGVmYXVsdCgpLHRoaXMuc3RhcnRUb3VjaFBhbihlKSkpfSx7cGFzc2l2ZTohMX0pLHR5cGVvZiB3aW5kb3c8InUiJiYiR2VzdHVyZUV2ZW50ImluIHdpbmRvdyYmKHRoaXMuZXZlbnRzLm9uTm9uUGFzc2l2ZSh0aGlzLmNvbnRhaW5lciwiZ2VzdHVyZXN0YXJ0IixlPT57ZS5wcmV2ZW50RGVmYXVsdCgpLHRoaXMuaW5pdGlhbFBpbmNoWm9vbT10aGlzLnpvb21QYW4uZ2V0Wm9vbSgpO2xldCB0PWUsbz10aGlzLmNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTt0LmNsaWVudFgtby5sZWZ0LHQuY2xpZW50WS1vLnRvcH0pLHRoaXMuZXZlbnRzLm9uTm9uUGFzc2l2ZSh0aGlzLmNvbnRhaW5lciwiZ2VzdHVyZWNoYW5nZSIsZT0+e2UucHJldmVudERlZmF1bHQoKTtsZXQgdD1lLG89dGhpcy5jb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7dGhpcy56b29tUGFuLnNldFpvb20odGhpcy5pbml0aWFsUGluY2hab29tKnQuc2NhbGUsdC5jbGllbnRYLW8ubGVmdCx0LmNsaWVudFktby50b3ApfSkpfXN0YXJ0UGFuKGUsdCl7dGhpcy5jbGVhbnVwV2luZG93TGlzdGVuZXJzKCksdGhpcy5hYm9ydENvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcjtsZXQgbz10aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWw7dGhpcy5pc1Bhbm5pbmc9ITEsdGhpcy5sYXN0UGFuWD1lLHRoaXMubGFzdFBhblk9dDtsZXQgbj1lLHI9dCxzPWY9PntsZXQgYT1mLmNsaWVudFgtdGhpcy5sYXN0UGFuWCxsPWYuY2xpZW50WS10aGlzLmxhc3RQYW5ZO2lmKCF0aGlzLmlzUGFubmluZyl7bGV0IGI9Zi5jbGllbnRYLW4sZz1mLmNsaWVudFktcjtpZihNYXRoLmh5cG90KGIsZyk8dHQpcmV0dXJuO3RoaXMuY29udGFpbmVyLl9fZWRCZWZvcmVBZnRlclN1cHByZXNzQ2xpY2s9ITAsdGhpcy5pc1Bhbm5pbmc9ITAsdGhpcy5jb250YWluZXIuc3R5bGUuY3Vyc29yPSJncmFiYmluZyJ9dGhpcy5sYXN0UGFuWD1mLmNsaWVudFgsdGhpcy5sYXN0UGFuWT1mLmNsaWVudFksdGhpcy56b29tUGFuLnBhbihhLGwpfSxoPSgpPT57dGhpcy5pc1Bhbm5pbmc9ITEsdGhpcy5jb250YWluZXIuc3R5bGUuY3Vyc29yPSIiLHRoaXMuY2xlYW51cFdpbmRvd0xpc3RlbmVycygpfTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigibW91c2Vtb3ZlIixzLHtzaWduYWw6b30pLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJtb3VzZXVwIixoLHtzaWduYWw6b30pfXN0YXJ0VG91Y2hQYW4oZSl7dGhpcy5jbGVhbnVwV2luZG93TGlzdGVuZXJzKCksdGhpcy5hYm9ydENvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcjtsZXQgdD10aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwsbz1lLnRvdWNoZXNbMF07dGhpcy5sYXN0UGFuWD1vLmNsaWVudFgsdGhpcy5sYXN0UGFuWT1vLmNsaWVudFk7bGV0IG49cz0+e2lmKHMudG91Y2hlcy5sZW5ndGghPT0xKXJldHVybjtzLnByZXZlbnREZWZhdWx0KCksdGhpcy5jb250YWluZXIuX19lZEJlZm9yZUFmdGVyU3VwcHJlc3NDbGljaz0hMDtsZXQgaD1zLnRvdWNoZXNbMF0sZj1oLmNsaWVudFgtdGhpcy5sYXN0UGFuWCxhPWguY2xpZW50WS10aGlzLmxhc3RQYW5ZO3RoaXMubGFzdFBhblg9aC5jbGllbnRYLHRoaXMubGFzdFBhblk9aC5jbGllbnRZLHRoaXMuem9vbVBhbi5wYW4oZixhKX0scj0oKT0+e3RoaXMuY2xlYW51cFdpbmRvd0xpc3RlbmVycygpfTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigidG91Y2htb3ZlIixuLHtwYXNzaXZlOiExLHNpZ25hbDp0fSksd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoZW5kIixyLHtzaWduYWw6dH0pLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ0b3VjaGNhbmNlbCIscix7c2lnbmFsOnR9KX1zdGFydFBpbmNoKGUpe2lmKGUudG91Y2hlcy5sZW5ndGg8MilyZXR1cm47dGhpcy5jbGVhbnVwV2luZG93TGlzdGVuZXJzKCksdGhpcy5hYm9ydENvbnRyb2xsZXI9bmV3IEFib3J0Q29udHJvbGxlcjtsZXQgdD10aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwsW28sbl09W2UudG91Y2hlc1swXSxlLnRvdWNoZXNbMV1dO3RoaXMuaW5pdGlhbFBpbmNoRGlzdGFuY2U9TWF0aC5oeXBvdChuLmNsaWVudFgtby5jbGllbnRYLG4uY2xpZW50WS1vLmNsaWVudFkpLHRoaXMuaW5pdGlhbFBpbmNoRGlzdGFuY2U9PT0wJiYodGhpcy5pbml0aWFsUGluY2hEaXN0YW5jZT0xKSx0aGlzLmluaXRpYWxQaW5jaFpvb209dGhpcy56b29tUGFuLmdldFpvb20oKTtsZXQgcj10aGlzLmNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxzPShvLmNsaWVudFgrbi5jbGllbnRYKS8yLXIubGVmdCxoPShvLmNsaWVudFkrbi5jbGllbnRZKS8yLXIudG9wLGY9bD0+e2lmKGwudG91Y2hlcy5sZW5ndGghPT0yKXJldHVybjtsLnByZXZlbnREZWZhdWx0KCk7bGV0W2IsZ109W2wudG91Y2hlc1swXSxsLnRvdWNoZXNbMV1dLHc9TWF0aC5oeXBvdChnLmNsaWVudFgtYi5jbGllbnRYLGcuY2xpZW50WS1iLmNsaWVudFkpL3RoaXMuaW5pdGlhbFBpbmNoRGlzdGFuY2U7dGhpcy56b29tUGFuLnNldFpvb20odGhpcy5pbml0aWFsUGluY2hab29tKncscyxoKX0sYT0oKT0+e3RoaXMuY2xlYW51cFdpbmRvd0xpc3RlbmVycygpfTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigidG91Y2htb3ZlIixmLHtwYXNzaXZlOiExLHNpZ25hbDp0fSksd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoZW5kIixhLHtzaWduYWw6dH0pLHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ0b3VjaGNhbmNlbCIsYSx7c2lnbmFsOnR9KX1jbGVhbnVwV2luZG93TGlzdGVuZXJzKCl7dGhpcy5hYm9ydENvbnRyb2xsZXImJih0aGlzLmFib3J0Q29udHJvbGxlci5hYm9ydCgpLHRoaXMuYWJvcnRDb250cm9sbGVyPW51bGwpfWRlc3Ryb3koKXt0aGlzLmNsZWFudXBXaW5kb3dMaXN0ZW5lcnMoKSx0aGlzLmV2ZW50cy5kZXN0cm95KCl9fSxpdD0nPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGQ9Ik01IDEyaDE0Ii8+PHBhdGggZD0iTTEyIDV2MTQiLz48L3N2Zz4nLG90PSc8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjE4IiBoZWlnaHQ9IjE4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTUgMTJoMTQiLz48L3N2Zz4nLG50PSc8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjE4IiBoZWlnaHQ9IjE4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTMgMTJhOSA5IDAgMSAwIDktOSA5Ljc1IDkuNzUgMCAwIDAtNi43NCAyLjc0TDMgOCIvPjxwYXRoIGQ9Ik0zIDN2NWg1Ii8+PC9zdmc+JztmdW5jdGlvbiBwZShpLGUpe2xldCB0PW5ldyBFLG89digiZGl2IixgY2ktYmVmb3JlLWFmdGVyLXpvb20tY29udHJvbHMgY2ktYmVmb3JlLWFmdGVyLXpvb20tY29udHJvbHMtLSR7aX1gKSxuPXYoImJ1dHRvbiIsImNpLWJlZm9yZS1hZnRlci16b29tLWluIix7dHlwZToiYnV0dG9uIiwiYXJpYS1sYWJlbCI6Ilpvb20gaW4ifSk7bi5pbm5lckhUTUw9aXQsdC5vbihuLCJjbGljayIsZS5vblpvb21Jbik7bGV0IHI9digiYnV0dG9uIiwiY2ktYmVmb3JlLWFmdGVyLXpvb20tb3V0Iix7dHlwZToiYnV0dG9uIiwiYXJpYS1sYWJlbCI6Ilpvb20gb3V0In0pO3IuaW5uZXJIVE1MPW90LHQub24ociwiY2xpY2siLGUub25ab29tT3V0KTtsZXQgcz12KCJidXR0b24iLCJjaS1iZWZvcmUtYWZ0ZXItem9vbS1yZXNldCIse3R5cGU6ImJ1dHRvbiIsImFyaWEtbGFiZWwiOiJSZXNldCB6b29tIn0pO3JldHVybiBzLmlubmVySFRNTD1udCx0Lm9uKHMsImNsaWNrIixlLm9uUmVzZXQpLG8uYXBwZW5kKG4scixzKSx7ZWxlbWVudDpvLGV2ZW50czp0fX12YXIgWD1jbGFzc3tjb25zdHJ1Y3RvcihlKXt0aGlzLnRpbWVvdXQ9bnVsbCx0aGlzLmVsPXYoImRpdiIsImNpLWJlZm9yZS1hZnRlci1zY3JvbGwtaGludCIseyJhcmlhLWhpZGRlbiI6InRydWUifSk7bGV0IHQ9dHlwZW9mIG5hdmlnYXRvcjwidSImJi9NYWN8aVBob25lfGlQYWR8aVBvZC8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTt0aGlzLmVsLnRleHRDb250ZW50PXQ/Ilx1MjMxOCArIHNjcm9sbCBvciBwaW5jaCB0byB6b29tIjoiQ3RybCArIHNjcm9sbCBvciBwaW5jaCB0byB6b29tIixlLmFwcGVuZENoaWxkKHRoaXMuZWwpfXNob3coKXt0aGlzLnRpbWVvdXQmJmNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXQpLHRoaXMuZWwuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLXNjcm9sbC1oaW50LS12aXNpYmxlIiksdGhpcy50aW1lb3V0PXNldFRpbWVvdXQoKCk9Pnt0aGlzLmVsLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1zY3JvbGwtaGludC0tdmlzaWJsZSIpLHRoaXMudGltZW91dD1udWxsfSwxNTAwKX1kZXN0cm95KCl7dGhpcy50aW1lb3V0JiZjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0KSx0aGlzLmVsLnJlbW92ZSgpfX07ZnVuY3Rpb24gdmUoaSxlLHQsbyl7bGV0IG49YGNpLWJlZm9yZS1hZnRlci1sYWJlbC0tJHt0fWAscj12KCJkaXYiLGBjaS1iZWZvcmUtYWZ0ZXItbGFiZWwgY2ktYmVmb3JlLWFmdGVyLWxhYmVsLWJlZm9yZSAke259YCx7ImFyaWEtaGlkZGVuIjoidHJ1ZSJ9KTtyLnRleHRDb250ZW50PWk7bGV0IHM9digiZGl2IixgY2ktYmVmb3JlLWFmdGVyLWxhYmVsIGNpLWJlZm9yZS1hZnRlci1sYWJlbC1hZnRlciAke259YCx7ImFyaWEtaGlkZGVuIjoidHJ1ZSJ9KTtyZXR1cm4gcy50ZXh0Q29udGVudD1lLHtiZWZvcmU6cixhZnRlcjpzfX1mdW5jdGlvbiB5ZShpLGUsdCxvKXtpZighaXx8IWUpcmV0dXJuO2xldCBuPTE1O3Q8bj9pLmNsYXNzTGlzdC5hZGQoImNpLWJlZm9yZS1hZnRlci1sYWJlbC0taGlkZGVuIik6aS5jbGFzc0xpc3QucmVtb3ZlKCJjaS1iZWZvcmUtYWZ0ZXItbGFiZWwtLWhpZGRlbiIpLHQ+MTAwLW4/ZS5jbGFzc0xpc3QuYWRkKCJjaS1iZWZvcmUtYWZ0ZXItbGFiZWwtLWhpZGRlbiIpOmUuY2xhc3NMaXN0LnJlbW92ZSgiY2ktYmVmb3JlLWFmdGVyLWxhYmVsLS1oaWRkZW4iKX12YXIgd2U9JzxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWxpbmUgcG9pbnRzPSIxNSAzIDIxIDMgMjEgOSIvPjxwb2x5bGluZSBwb2ludHM9IjkgMjEgMyAyMSAzIDE1Ii8+PGxpbmUgeDE9IjIxIiB4Mj0iMTQiIHkxPSIzIiB5Mj0iMTAiLz48bGluZSB4MT0iMyIgeDI9IjEwIiB5MT0iMjEiIHkyPSIxNCIvPjwvc3ZnPicscnQ9JzxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWxpbmUgcG9pbnRzPSI0IDE0IDEwIDE0IDEwIDIwIi8+PHBvbHlsaW5lIHBvaW50cz0iMjAgMTAgMTQgMTAgMTQgNCIvPjxsaW5lIHgxPSIxNCIgeDI9IjIxIiB5MT0iMTAiIHkyPSIzIi8+PGxpbmUgeDE9IjMiIHgyPSIxMCIgeTE9IjIxIiB5Mj0iMTQiLz48L3N2Zz4nLF89Y2xhc3N7Y29uc3RydWN0b3IoZSx0KXt0aGlzLmNvbnRhaW5lcj1lLHRoaXMuZnVsbHNjcmVlblRhcmdldD1lLmNsb3Nlc3QoIi5lZC1iZWZvcmUtYWZ0ZXIiKXx8ZSx0aGlzLm9uRnVsbHNjcmVlbkNoYW5nZT10LHRoaXMuYnV0dG9uPW51bGwsdGhpcy5ldmVudHM9bmV3IEUsdGhpcy5pc0FjdGl2ZT0hMSxRKCkmJih0aGlzLmNyZWF0ZUJ1dHRvbigpLHRoaXMuYmluZEV2ZW50cygpKX1jcmVhdGVCdXR0b24oKXt0aGlzLmJ1dHRvbj12KCJidXR0b24iLCJjaS1iZWZvcmUtYWZ0ZXItZnVsbHNjcmVlbi1idG4iLHt0eXBlOiJidXR0b24iLCJhcmlhLWxhYmVsIjoiRW50ZXIgZnVsbHNjcmVlbiIsImFyaWEtcHJlc3NlZCI6ImZhbHNlIn0pLHRoaXMuYnV0dG9uLmlubmVySFRNTD13ZSx0aGlzLmV2ZW50cy5vbih0aGlzLmJ1dHRvbiwiY2xpY2siLCgpPT57dGhpcy50b2dnbGUoKS5jYXRjaCgoKT0+e30pfSksdGhpcy5jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5idXR0b24pfWJpbmRFdmVudHMoKXt0aGlzLmV2ZW50cy5vbihkb2N1bWVudCwiZnVsbHNjcmVlbmNoYW5nZSIsKCk9PnRoaXMuaGFuZGxlQ2hhbmdlKCkpLHRoaXMuZXZlbnRzLm9uKGRvY3VtZW50LCJ3ZWJraXRmdWxsc2NyZWVuY2hhbmdlIiwoKT0+dGhpcy5oYW5kbGVDaGFuZ2UoKSl9aGFuZGxlQ2hhbmdlKCl7dmFyIGU7bGV0IHQ9dWUoKSxvPXRoaXMuaXNBY3RpdmU7dGhpcy5pc0FjdGl2ZT10PT09dGhpcy5mdWxsc2NyZWVuVGFyZ2V0LG8hPT10aGlzLmlzQWN0aXZlJiYodGhpcy5jb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZSgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0tZnVsbHNjcmVlbiIsdGhpcy5pc0FjdGl2ZSksdGhpcy5idXR0b24mJih0aGlzLmJ1dHRvbi5pbm5lckhUTUw9dGhpcy5pc0FjdGl2ZT9ydDp3ZSx0aGlzLmJ1dHRvbi5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLHRoaXMuaXNBY3RpdmU/IkV4aXQgZnVsbHNjcmVlbiI6IkVudGVyIGZ1bGxzY3JlZW4iKSx0aGlzLmJ1dHRvbi5zZXRBdHRyaWJ1dGUoImFyaWEtcHJlc3NlZCIsU3RyaW5nKHRoaXMuaXNBY3RpdmUpKSksKGU9dGhpcy5vbkZ1bGxzY3JlZW5DaGFuZ2UpPT1udWxsfHxlLmNhbGwodGhpcyx0aGlzLmlzQWN0aXZlKSl9YXN5bmMgZW50ZXIoKXtRKCkmJmF3YWl0IEZlKHRoaXMuZnVsbHNjcmVlblRhcmdldCl9YXN5bmMgZXhpdCgpe1EoKSYmdWUoKT09PXRoaXMuZnVsbHNjcmVlblRhcmdldCYmYXdhaXQgbWUoKX1hc3luYyB0b2dnbGUoKXt0aGlzLmlzQWN0aXZlP2F3YWl0IHRoaXMuZXhpdCgpOmF3YWl0IHRoaXMuZW50ZXIoKX1nZXRJc0Z1bGxzY3JlZW4oKXtyZXR1cm4gdGhpcy5pc0FjdGl2ZX1kZXN0cm95KCl7dmFyIGUsdDtsZXQgbz10aGlzLmlzQWN0aXZlO3RoaXMuZXZlbnRzLmRlc3Ryb3koKSxvJiYodGhpcy5pc0FjdGl2ZT0hMSwoZT10aGlzLm9uRnVsbHNjcmVlbkNoYW5nZSk9PW51bGx8fGUuY2FsbCh0aGlzLCExKSxtZSgpLmNhdGNoKCgpPT57fSkpLHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLWZ1bGxzY3JlZW4iKSwodD10aGlzLmJ1dHRvbik9PW51bGx8fHQucmVtb3ZlKCl9fSxpZT1jbGFzc3tjb25zdHJ1Y3RvcihlLHQsbyxuLHIscyl7dGhpcy5jb250YWluZXI9ZSx0aGlzLmR1cmF0aW9uPXQsdGhpcy5kZWxheT1vLHRoaXMuZWFzaW5nPW4sdGhpcy5hbmltYXRlT25jZT1yLHRoaXMub25BbmltYXRlPXMsdGhpcy5vYnNlcnZlcj1udWxsLHRoaXMuaGFzUGxheWVkPSExLHRoaXMuaXNBbmltYXRpbmc9ITEsdGhpcy5kZWxheVRpbWVyPW51bGwsdGhpcy5kdXJhdGlvblRpbWVyPW51bGwsdGhpcy5vYnNlcnZlKCl9b2JzZXJ2ZSgpe3R5cGVvZiBJbnRlcnNlY3Rpb25PYnNlcnZlcj4idSJ8fCh0aGlzLm9ic2VydmVyPW5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihlPT57Zm9yKGxldCB0IG9mIGUpaWYodC5pc0ludGVyc2VjdGluZyl7aWYodGhpcy5hbmltYXRlT25jZSYmdGhpcy5oYXNQbGF5ZWR8fHRoaXMuaXNBbmltYXRpbmcpY29udGludWU7dGhpcy5wbGF5KCl9fSx7dGhyZXNob2xkOi4zfSksdGhpcy5vYnNlcnZlci5vYnNlcnZlKHRoaXMuY29udGFpbmVyKSl9cGxheSgpe3ZhciBlLHQ7aWYodGhpcy5oYXNQbGF5ZWQ9ITAsdGhpcy5pc0FuaW1hdGluZz0hMCx0eXBlb2Ygd2luZG93PCJ1IiYmKGU9d2luZG93Lm1hdGNoTWVkaWEpIT1udWxsJiZlLmNhbGwod2luZG93LCIocHJlZmVycy1yZWR1Y2VkLW1vdGlvbjogcmVkdWNlKSIpLm1hdGNoZXMpe3RoaXMub25BbmltYXRlKCEwKSx0aGlzLmlzQW5pbWF0aW5nPSExLHRoaXMuYW5pbWF0ZU9uY2UmJigodD10aGlzLm9ic2VydmVyKT09bnVsbHx8dC5kaXNjb25uZWN0KCkpO3JldHVybn10aGlzLm9uQW5pbWF0ZSgicmVzZXQiKSx0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJjaS1iZWZvcmUtYWZ0ZXItYW5pbWF0ZS1lbnRyYW5jZSIpLHRoaXMuY29udGFpbmVyLnN0eWxlLnNldFByb3BlcnR5KCItLWNpLWJlZm9yZS1hZnRlci1hbmltYXRlLWR1cmF0aW9uIixgJHt0aGlzLmR1cmF0aW9ufW1zYCksdGhpcy5jb250YWluZXIuc3R5bGUuc2V0UHJvcGVydHkoIi0tY2ktYmVmb3JlLWFmdGVyLWFuaW1hdGUtZWFzaW5nIix0aGlzLmVhc2luZyksdGhpcy5kZWxheVRpbWVyPXNldFRpbWVvdXQoKCk9Pnt0aGlzLmRlbGF5VGltZXI9bnVsbCx0aGlzLm9uQW5pbWF0ZSghMSksdGhpcy5kdXJhdGlvblRpbWVyPXNldFRpbWVvdXQoKCk9Pnt2YXIgbzt0aGlzLmR1cmF0aW9uVGltZXI9bnVsbCx0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKCJjaS1iZWZvcmUtYWZ0ZXItYW5pbWF0ZS1lbnRyYW5jZSIpLHRoaXMuaXNBbmltYXRpbmc9ITEsdGhpcy5hbmltYXRlT25jZSYmKChvPXRoaXMub2JzZXJ2ZXIpPT1udWxsfHxvLmRpc2Nvbm5lY3QoKSl9LHRoaXMuZHVyYXRpb24pfSx0aGlzLmRlbGF5KX1nZXRIYXNQbGF5ZWQoKXtyZXR1cm4gdGhpcy5oYXNQbGF5ZWR9ZGVzdHJveSgpe3ZhciBlO3RoaXMuZGVsYXlUaW1lciYmY2xlYXJUaW1lb3V0KHRoaXMuZGVsYXlUaW1lciksdGhpcy5kdXJhdGlvblRpbWVyJiZjbGVhclRpbWVvdXQodGhpcy5kdXJhdGlvblRpbWVyKSx0aGlzLmRlbGF5VGltZXI9bnVsbCx0aGlzLmR1cmF0aW9uVGltZXI9bnVsbCx0aGlzLmlzQW5pbWF0aW5nPSExLHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1hbmltYXRlLWVudHJhbmNlIiksdGhpcy5jb250YWluZXIuc3R5bGUucmVtb3ZlUHJvcGVydHkoIi0tY2ktYmVmb3JlLWFmdGVyLWFuaW1hdGUtZHVyYXRpb24iKSx0aGlzLmNvbnRhaW5lci5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiLS1jaS1iZWZvcmUtYWZ0ZXItYW5pbWF0ZS1lYXNpbmciKSwoZT10aGlzLm9ic2VydmVyKT09bnVsbHx8ZS5kaXNjb25uZWN0KCksdGhpcy5vYnNlcnZlcj1udWxsfX0sVz1jbGFzc3tjb25zdHJ1Y3RvcihlLHQsbyxuLHIscyl7dGhpcy5oYW5kbGU9ZSx0aGlzLm9yaWVudGF0aW9uPXQsdGhpcy5zdGVwPW8sdGhpcy5sYXJnZVN0ZXA9bix0aGlzLnpvb21FbmFibGVkPXIsdGhpcy5jYWxsYmFja3M9cyx0aGlzLmV2ZW50cz1uZXcgRSx0aGlzLmJpbmQoKX1iaW5kKCl7dGhpcy5ldmVudHMub24odGhpcy5oYW5kbGUsImtleWRvd24iLGU9Pnt0aGlzLmhhbmRsZUtleURvd24oZSl9KX1oYW5kbGVLZXlEb3duKGUpe3ZhciB0LG8sbixyLHMsaDtpZihlLmN0cmxLZXl8fGUuYWx0S2V5fHxlLm1ldGFLZXkpcmV0dXJuO2xldCBmPXRoaXMuY2FsbGJhY2tzLmdldFBvc2l0aW9uKCksYT1lLnNoaWZ0S2V5P3RoaXMubGFyZ2VTdGVwOnRoaXMuc3RlcCxsPW51bGw7aWYodGhpcy5vcmllbnRhdGlvbj09PSJob3Jpem9udGFsIilzd2l0Y2goZS5rZXkpe2Nhc2UiQXJyb3dMZWZ0IjpsPWYtYTticmVhaztjYXNlIkFycm93UmlnaHQiOmw9ZithO2JyZWFrfWVsc2Ugc3dpdGNoKGUua2V5KXtjYXNlIkFycm93VXAiOmw9Zi1hO2JyZWFrO2Nhc2UiQXJyb3dEb3duIjpsPWYrYTticmVha31zd2l0Y2goZS5rZXkpe2Nhc2UiSG9tZSI6bD0wO2JyZWFrO2Nhc2UiRW5kIjpsPTEwMDticmVha31pZihsIT09bnVsbCl7ZS5wcmV2ZW50RGVmYXVsdCgpLGw9TWF0aC5tYXgoMCxNYXRoLm1pbigxMDAsbCkpLHRoaXMuY2FsbGJhY2tzLm9uUG9zaXRpb25DaGFuZ2UobCk7cmV0dXJufWlmKHRoaXMuem9vbUVuYWJsZWQpc3dpdGNoKGUua2V5KXtjYXNlIisiOmNhc2UiPSI6ZS5wcmV2ZW50RGVmYXVsdCgpLChvPSh0PXRoaXMuY2FsbGJhY2tzKS5vblpvb21Jbik9PW51bGx8fG8uY2FsbCh0KTticmVhaztjYXNlIi0iOmUucHJldmVudERlZmF1bHQoKSwocj0obj10aGlzLmNhbGxiYWNrcykub25ab29tT3V0KT09bnVsbHx8ci5jYWxsKG4pO2JyZWFrO2Nhc2UiMCI6ZS5wcmV2ZW50RGVmYXVsdCgpLChoPShzPXRoaXMuY2FsbGJhY2tzKS5vblpvb21SZXNldCk9PW51bGx8fGguY2FsbChzKTticmVha319dXBkYXRlQ29uZmlnKGUsdCxvLG4pe3RoaXMub3JpZW50YXRpb249ZSx0aGlzLnN0ZXA9dCx0aGlzLmxhcmdlU3RlcD1vLHRoaXMuem9vbUVuYWJsZWQ9bn1kZXN0cm95KCl7dGhpcy5ldmVudHMuZGVzdHJveSgpfX07ZnVuY3Rpb24gc3QoaSxlKXtpLnNldEF0dHJpYnV0ZSgiYXJpYS12YWx1ZW5vdyIsU3RyaW5nKE1hdGgucm91bmQoZSkpKX1mdW5jdGlvbiBhdChpKXtpLnNldEF0dHJpYnV0ZSgicm9sZSIsImdyb3VwIiksaS5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLCJCZWZvcmUgYW5kIGFmdGVyIGltYWdlIGNvbXBhcmlzb24iKX12YXIgcT1jbGFzc3tjb25zdHJ1Y3RvcihlLHQpe3RoaXMuZXZlbnRzPW5ldyBFLHRoaXMuaW1hZ2VFdmVudHM9bmV3IEUsdGhpcy5zbGlkZXJHZXN0dXJlcz1udWxsLHRoaXMuem9vbVBhbj1udWxsLHRoaXMuem9vbUdlc3R1cmVzPW51bGwsdGhpcy5zY3JvbGxIaW50PW51bGwsdGhpcy5mdWxsc2NyZWVuTWFuYWdlcj1udWxsLHRoaXMuZW50cmFuY2VBbmltYXRpb249bnVsbCx0aGlzLmtleWJvYXJkSGFuZGxlcj1udWxsLHRoaXMucmVzaXplT2JzZXJ2ZXI9bnVsbCx0aGlzLnpvb21Db250cm9sc0VsPW51bGwsdGhpcy56b29tQ29udHJvbHNFdmVudHM9bnVsbCx0aGlzLmxhenlMb2FkT2JzZXJ2ZXI9bnVsbCx0aGlzLnJlc2l6ZURlYm91bmNlVGltZXI9bnVsbCx0aGlzLmFuaW1UcmFuc2l0aW9uVGltZXI9bnVsbCx0aGlzLnN1cHByZXNzQ2FsbGJhY2tzPSExO2xldCBvPU9lKGUpO3RoaXMudXNlckNvbmZpZz17Li4udH0sdGhpcy5jb25maWc9ZGUodCksdGhpcy5zdGF0ZT17cG9zaXRpb246dGhpcy5jb25maWcuaW5pdGlhbFBvc2l0aW9uLGlzRHJhZ2dpbmc6ITEsem9vbUxldmVsOjEscGFuWDowLHBhblk6MCxpc1JlYWR5OiExLGlzRnVsbHNjcmVlbjohMX0sdGhpcy5idWlsZERPTShvKSx0aGlzLmluaXRNb2R1bGVzKCksdGhpcy5sb2FkSW1hZ2VzKCl9Z2V0RWxlbWVudHMoKXtyZXR1cm57Y29udGFpbmVyOnRoaXMuZWxlbWVudHMuY29udGFpbmVyLHZpZXdwb3J0OnRoaXMuZWxlbWVudHMudmlld3BvcnQsYmVmb3JlSW1hZ2U6dGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZSxhZnRlckltYWdlOnRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZSxoYW5kbGU6dGhpcy5lbGVtZW50cy5oYW5kbGV9fXNldFBvc2l0aW9uKGUpe2xldCB0PWJlKGUpO3RoaXMudXBkYXRlUG9zaXRpb24odCl9Z2V0UG9zaXRpb24oKXtyZXR1cm4gdGhpcy5zdGF0ZS5wb3NpdGlvbn1zZXRab29tKGUpe3ZhciB0Oyh0PXRoaXMuem9vbVBhbik9PW51bGx8fHQuc2V0Wm9vbShlKX1nZXRab29tKCl7dmFyIGU7cmV0dXJuKChlPXRoaXMuem9vbVBhbik9PW51bGw/dm9pZCAwOmUuZ2V0Wm9vbSgpKT8/MX1yZXNldFpvb20oKXt2YXIgZTsoZT10aGlzLnpvb21QYW4pPT1udWxsfHxlLnJlc2V0Wm9vbSgpfXBhbkJ5KGUsdCl7dGhpcy56b29tUGFuJiZOdW1iZXIuaXNGaW5pdGUoZSkmJk51bWJlci5pc0Zpbml0ZSh0KSYmdGhpcy56b29tUGFuLnBhbihlLHQpfWNhbmNlbEVudHJhbmNlKCl7dGhpcy5lbnRyYW5jZUFuaW1hdGlvbj8uZGVzdHJveSgpLHRoaXMuZW50cmFuY2VBbmltYXRpb249bnVsbCx0aGlzLmFuaW1UcmFuc2l0aW9uVGltZXIhPT1udWxsJiZjbGVhclRpbWVvdXQodGhpcy5hbmltVHJhbnNpdGlvblRpbWVyKSx0aGlzLmFuaW1UcmFuc2l0aW9uVGltZXI9bnVsbCx0aGlzLmVsZW1lbnRzLmhhbmRsZS5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMuZWxlbWVudHMuY2xpcC5zdHlsZS50cmFuc2l0aW9uPSIifWVudGVyRnVsbHNjcmVlbigpe3ZhciBlOyhlPXRoaXMuZnVsbHNjcmVlbk1hbmFnZXIpPT1udWxsfHxlLmVudGVyKCkuY2F0Y2goKCk9Pnt9KX1leGl0RnVsbHNjcmVlbigpe3ZhciBlOyhlPXRoaXMuZnVsbHNjcmVlbk1hbmFnZXIpPT1udWxsfHxlLmV4aXQoKS5jYXRjaCgoKT0+e30pfWlzRnVsbHNjcmVlbigpe3ZhciBlO3JldHVybigoZT10aGlzLmZ1bGxzY3JlZW5NYW5hZ2VyKT09bnVsbD92b2lkIDA6ZS5nZXRJc0Z1bGxzY3JlZW4oKSk/PyExfXVwZGF0ZShlKXt2YXIgdCxvLG4scixzLGgsZixhO3RoaXMudXNlckNvbmZpZz17Li4udGhpcy51c2VyQ29uZmlnLC4uLmV9O2xldCBsPXRoaXMuY29uZmlnO3RoaXMuY29uZmlnPWRlKHRoaXMudXNlckNvbmZpZyk7bGV0IGI9dGhpcy5jb25maWcuYmVmb3JlU3JjIT09bC5iZWZvcmVTcmMsZz10aGlzLmNvbmZpZy5hZnRlclNyYyE9PWwuYWZ0ZXJTcmMsdz0hbHQodGhpcy5jb25maWcuY2xvdWRpbWFnZSxsLmNsb3VkaW1hZ2UpO2lmKChifHxnfHx3KSYmKHRoaXMubGF6eUxvYWRPYnNlcnZlciYmKHRoaXMubGF6eUxvYWRPYnNlcnZlci5kaXNjb25uZWN0KCksdGhpcy5sYXp5TG9hZE9ic2VydmVyPW51bGwpLHRoaXMuc3RhdGUuaXNSZWFkeT0hMSx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJjaS1iZWZvcmUtYWZ0ZXItbG9hZGluZyIpLChifHx3KSYmKHRoaXMuZWxlbWVudHMuYmVmb3JlSW1hZ2Uuc3JjPXRoaXMucmVzb2x2ZUltYWdlU3JjKHRoaXMuY29uZmlnLmJlZm9yZVNyYykpLChnfHx3KSYmKHRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zcmM9dGhpcy5yZXNvbHZlSW1hZ2VTcmModGhpcy5jb25maWcuYWZ0ZXJTcmMpKSx0aGlzLnJlZ2lzdGVySW1hZ2VMb2FkSGFuZGxlcnMoYnx8dyxnfHx3KSx0aGlzLmNvbmZpZy5jbG91ZGltYWdlJiYhbC5jbG91ZGltYWdlP3RoaXMuaW5pdFJlc2l6ZU9ic2VydmVyKCk6IXRoaXMuY29uZmlnLmNsb3VkaW1hZ2UmJmwuY2xvdWRpbWFnZSYmKCh0PXRoaXMucmVzaXplT2JzZXJ2ZXIpPT1udWxsfHx0LmRpc2Nvbm5lY3QoKSx0aGlzLnJlc2l6ZU9ic2VydmVyPW51bGwpKSx0aGlzLmNvbmZpZy5iZWZvcmVBbHQhPT1sLmJlZm9yZUFsdCYmdGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZS5zZXRBdHRyaWJ1dGUoImFsdCIsdGhpcy5jb25maWcuYmVmb3JlQWx0KSx0aGlzLmNvbmZpZy5hZnRlckFsdCE9PWwuYWZ0ZXJBbHQmJnRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zZXRBdHRyaWJ1dGUoImFsdCIsdGhpcy5jb25maWcuYWZ0ZXJBbHQpLHRoaXMuY29uZmlnLmFzcGVjdFJhdGlvIT09bC5hc3BlY3RSYXRpbyYmKHRoaXMuZWxlbWVudHMud3JhcHBlci5zdHlsZS5hc3BlY3RSYXRpbz10aGlzLmNvbmZpZy5hc3BlY3RSYXRpb3x8IiIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoImNpLWJlZm9yZS1hZnRlci10aGVtZS1kYXJrIix0aGlzLmNvbmZpZy50aGVtZT09PSJkYXJrIiksdGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZSgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0taG9yaXpvbnRhbCIsdGhpcy5jb25maWcub3JpZW50YXRpb249PT0iaG9yaXpvbnRhbCIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLXZlcnRpY2FsIix0aGlzLmNvbmZpZy5vcmllbnRhdGlvbj09PSJ2ZXJ0aWNhbCIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLWhvdmVyLW1vZGUiLHRoaXMuY29uZmlnLm1vZGU9PT0iaG92ZXIiKSx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKCJjaS1iZWZvcmUtYWZ0ZXItY29udGFpbmVyLS1jbGljay1tb2RlIix0aGlzLmNvbmZpZy5tb2RlPT09ImNsaWNrIiksdGhpcy5lbGVtZW50cy52aWV3cG9ydC5jbGFzc0xpc3QudG9nZ2xlKCJjaS1iZWZvcmUtYWZ0ZXItdmlld3BvcnQtLXpvb21hYmxlIix0aGlzLmNvbmZpZy56b29tKSwodGhpcy5jb25maWcuaGFuZGxlU3R5bGUhPT1sLmhhbmRsZVN0eWxlfHx0aGlzLmNvbmZpZy5vcmllbnRhdGlvbiE9PWwub3JpZW50YXRpb24pJiZ0aGlzLnJlYnVpbGRIYW5kbGUoKSx0aGlzLmNvbmZpZy5tb2RlIT09bC5tb2RlJiYoKG89dGhpcy5zbGlkZXJHZXN0dXJlcyk9PW51bGx8fG8udXBkYXRlTW9kZSh0aGlzLmNvbmZpZy5tb2RlKSksdGhpcy5jb25maWcub3JpZW50YXRpb24hPT1sLm9yaWVudGF0aW9uJiYoKG49dGhpcy5zbGlkZXJHZXN0dXJlcyk9PW51bGx8fG4udXBkYXRlT3JpZW50YXRpb24odGhpcy5jb25maWcub3JpZW50YXRpb24pKSwodGhpcy5jb25maWcubGFiZWxzRW5hYmxlZCE9PWwubGFiZWxzRW5hYmxlZHx8dGhpcy5jb25maWcubGFiZWxCZWZvcmUhPT1sLmxhYmVsQmVmb3JlfHx0aGlzLmNvbmZpZy5sYWJlbEFmdGVyIT09bC5sYWJlbEFmdGVyfHx0aGlzLmNvbmZpZy5sYWJlbFBvc2l0aW9uIT09bC5sYWJlbFBvc2l0aW9ufHx0aGlzLmNvbmZpZy5vcmllbnRhdGlvbiE9PWwub3JpZW50YXRpb24pJiZ0aGlzLnJlYnVpbGRMYWJlbHMoKSx0aGlzLmNvbmZpZy56b29tIT09bC56b29tKXRoaXMucmVidWlsZFpvb20oKTtlbHNlIGlmKHRoaXMuem9vbVBhbiYmKHRoaXMuem9vbVBhbi51cGRhdGVDb25maWcodGhpcy5jb25maWcpLHRoaXMuY29uZmlnLnNjcm9sbEhpbnQhPT1sLnNjcm9sbEhpbnQmJigocj10aGlzLnNjcm9sbEhpbnQpPT1udWxsfHxyLmRlc3Ryb3koKSx0aGlzLnNjcm9sbEhpbnQ9bnVsbCx0aGlzLmNvbmZpZy5zY3JvbGxIaW50JiYodGhpcy5zY3JvbGxIaW50PW5ldyBYKHRoaXMuZWxlbWVudHMuY29udGFpbmVyKSkpLCh0aGlzLmNvbmZpZy56b29tQ29udHJvbHMhPT1sLnpvb21Db250cm9sc3x8dGhpcy5jb25maWcuem9vbUNvbnRyb2xzUG9zaXRpb24hPT1sLnpvb21Db250cm9sc1Bvc2l0aW9uKSYmKChzPXRoaXMuem9vbUNvbnRyb2xzRXZlbnRzKT09bnVsbHx8cy5kZXN0cm95KCksdGhpcy56b29tQ29udHJvbHNFdmVudHM9bnVsbCwoaD10aGlzLnpvb21Db250cm9sc0VsKT09bnVsbHx8aC5yZW1vdmUoKSx0aGlzLnpvb21Db250cm9sc0VsPW51bGwsdGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZSgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0tem9vbS10b3AtcmlnaHQiKSx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKCJjaS1iZWZvcmUtYWZ0ZXItY29udGFpbmVyLS16b29tLXRvcCIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLXpvb20tbGVmdCIpLHRoaXMuY29uZmlnLnpvb21Db250cm9scykpKXtsZXQgeD1wZSh0aGlzLmNvbmZpZy56b29tQ29udHJvbHNQb3NpdGlvbix7b25ab29tSW46KCk9Pnt2YXIgejtyZXR1cm4oej10aGlzLnpvb21QYW4pPT1udWxsP3ZvaWQgMDp6Lnpvb21JbigpfSxvblpvb21PdXQ6KCk9Pnt2YXIgejtyZXR1cm4oej10aGlzLnpvb21QYW4pPT1udWxsP3ZvaWQgMDp6Lnpvb21PdXQoKX0sb25SZXNldDooKT0+e3ZhciB6O3JldHVybih6PXRoaXMuem9vbVBhbik9PW51bGw/dm9pZCAwOnoucmVzZXRab29tKCl9fSk7dGhpcy56b29tQ29udHJvbHNFbD14LmVsZW1lbnQsdGhpcy56b29tQ29udHJvbHNFdmVudHM9eC5ldmVudHMsdGhpcy5lbGVtZW50cy5jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy56b29tQ29udHJvbHNFbCksdGhpcy5hcHBseVpvb21Qb3NpdGlvbkNsYXNzZXMoKX10aGlzLmNvbmZpZy5pbml0aWFsUG9zaXRpb24hPT1sLmluaXRpYWxQb3NpdGlvbiYmdGhpcy51cGRhdGVQb3NpdGlvbih0aGlzLmNvbmZpZy5pbml0aWFsUG9zaXRpb24pLHRoaXMuY29uZmlnLmZ1bGxzY3JlZW5CdXR0b24hPT1sLmZ1bGxzY3JlZW5CdXR0b24mJnRoaXMucmVidWlsZEZ1bGxzY3JlZW4oKSx0aGlzLmNvbmZpZy5hbmltYXRlRW5hYmxlZCE9PWwuYW5pbWF0ZUVuYWJsZWQmJigoZj10aGlzLmVudHJhbmNlQW5pbWF0aW9uKT09bnVsbHx8Zi5kZXN0cm95KCksdGhpcy5lbnRyYW5jZUFuaW1hdGlvbj1udWxsLHRoaXMuY29uZmlnLmFuaW1hdGVFbmFibGVkJiZ0aGlzLmluaXRFbnRyYW5jZUFuaW1hdGlvbigpKSwoYT10aGlzLmtleWJvYXJkSGFuZGxlcik9PW51bGx8fGEudXBkYXRlQ29uZmlnKHRoaXMuY29uZmlnLm9yaWVudGF0aW9uLHRoaXMuY29uZmlnLmtleWJvYXJkU3RlcCx0aGlzLmNvbmZpZy5rZXlib2FyZExhcmdlU3RlcCx0aGlzLmNvbmZpZy56b29tKSx0aGlzLnVwZGF0ZVBvc2l0aW9uKHRoaXMuc3RhdGUucG9zaXRpb24pfWRlc3Ryb3koKXt2YXIgZSx0LG8sbixyLHMsaCxmLGEsbCxiOyhlPXRoaXMuc2xpZGVyR2VzdHVyZXMpPT1udWxsfHxlLmRlc3Ryb3koKSwodD10aGlzLnpvb21HZXN0dXJlcyk9PW51bGx8fHQuZGVzdHJveSgpLChvPXRoaXMuem9vbVBhbik9PW51bGx8fG8uZGVzdHJveSgpLHRoaXMuem9vbVBhbj1udWxsLChuPXRoaXMuc2Nyb2xsSGludCk9PW51bGx8fG4uZGVzdHJveSgpLChyPXRoaXMuZnVsbHNjcmVlbk1hbmFnZXIpPT1udWxsfHxyLmRlc3Ryb3koKSwocz10aGlzLmVudHJhbmNlQW5pbWF0aW9uKT09bnVsbHx8cy5kZXN0cm95KCksKGg9dGhpcy5rZXlib2FyZEhhbmRsZXIpPT1udWxsfHxoLmRlc3Ryb3koKSx0aGlzLmV2ZW50cy5kZXN0cm95KCksdGhpcy5pbWFnZUV2ZW50cy5kZXN0cm95KCksKGY9dGhpcy5yZXNpemVPYnNlcnZlcik9PW51bGx8fGYuZGlzY29ubmVjdCgpLChhPXRoaXMubGF6eUxvYWRPYnNlcnZlcik9PW51bGx8fGEuZGlzY29ubmVjdCgpLHRoaXMubGF6eUxvYWRPYnNlcnZlcj1udWxsLChsPXRoaXMuem9vbUNvbnRyb2xzRXZlbnRzKT09bnVsbHx8bC5kZXN0cm95KCksdGhpcy56b29tQ29udHJvbHNFdmVudHM9bnVsbCwoYj10aGlzLnpvb21Db250cm9sc0VsKT09bnVsbHx8Yi5yZW1vdmUoKSx0aGlzLnJlc2l6ZURlYm91bmNlVGltZXImJmNsZWFyVGltZW91dCh0aGlzLnJlc2l6ZURlYm91bmNlVGltZXIpLHRoaXMuYW5pbVRyYW5zaXRpb25UaW1lciYmY2xlYXJUaW1lb3V0KHRoaXMuYW5pbVRyYW5zaXRpb25UaW1lciksdGhpcy5lbGVtZW50cy5jb250YWluZXIuaW5uZXJIVE1MPSIiLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLnJlbW92ZUF0dHJpYnV0ZSgicm9sZSIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLnJlbW92ZUF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTmFtZT10aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc05hbWUuc3BsaXQoIiAiKS5maWx0ZXIoZz0+IWcuc3RhcnRzV2l0aCgiY2ktYmVmb3JlLWFmdGVyIikpLmpvaW4oIiAiKX1idWlsZERPTShlKXtlLmlubmVySFRNTD0iIjtsZXQgdD1gY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0tJHt0aGlzLmNvbmZpZy5vcmllbnRhdGlvbn1gO2UuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lciIsdCksdGhpcy5jb25maWcubW9kZT09PSJob3ZlciImJmUuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0taG92ZXItbW9kZSIpLHRoaXMuY29uZmlnLm1vZGU9PT0iY2xpY2siJiZlLmNsYXNzTGlzdC5hZGQoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLWNsaWNrLW1vZGUiKSx0aGlzLmNvbmZpZy50aGVtZT09PSJkYXJrIiYmZS5jbGFzc0xpc3QuYWRkKCJjaS1iZWZvcmUtYWZ0ZXItdGhlbWUtZGFyayIpLGUuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLWxvYWRpbmciKSxhdChlKTtsZXQgbz12KCJkaXYiLCJjaS1iZWZvcmUtYWZ0ZXItdmlld3BvcnQiKTt0aGlzLmNvbmZpZy56b29tJiZvLmNsYXNzTGlzdC5hZGQoImNpLWJlZm9yZS1hZnRlci12aWV3cG9ydC0tem9vbWFibGUiKTtsZXQgbj12KCJkaXYiLCJjaS1iZWZvcmUtYWZ0ZXItd3JhcHBlciIpO3RoaXMuY29uZmlnLmFzcGVjdFJhdGlvJiYobi5zdHlsZS5hc3BlY3RSYXRpbz10aGlzLmNvbmZpZy5hc3BlY3RSYXRpbyk7bGV0IHI9digiaW1nIiwiY2ktYmVmb3JlLWFmdGVyLWltYWdlIGNpLWJlZm9yZS1hZnRlci1iZWZvcmUiLHthbHQ6dGhpcy5jb25maWcuYmVmb3JlQWx0LGRyYWdnYWJsZToiZmFsc2UiLHJvbGU6ImltZyJ9KSxzPXYoImRpdiIsImNpLWJlZm9yZS1hZnRlci1jbGlwIik7ZWUocyx0aGlzLnN0YXRlLnBvc2l0aW9uLHRoaXMuY29uZmlnLm9yaWVudGF0aW9uKTtsZXQgaD12KCJpbWciLCJjaS1iZWZvcmUtYWZ0ZXItaW1hZ2UgY2ktYmVmb3JlLWFmdGVyLWFmdGVyIix7YWx0OnRoaXMuY29uZmlnLmFmdGVyQWx0LGRyYWdnYWJsZToiZmFsc2UiLHJvbGU6ImltZyJ9KTtzLmFwcGVuZENoaWxkKGgpLG4uYXBwZW5kKHIscyksby5hcHBlbmRDaGlsZChuKSxlLmFwcGVuZENoaWxkKG8pO2xldCBmPWdlKHRoaXMuY29uZmlnLmhhbmRsZVN0eWxlLHRoaXMuY29uZmlnLm9yaWVudGF0aW9uLHRoaXMuc3RhdGUucG9zaXRpb24pO2UuYXBwZW5kQ2hpbGQoZik7bGV0IGE9Zi5xdWVyeVNlbGVjdG9yKCIuY2ktYmVmb3JlLWFmdGVyLWhhbmRsZS1ncmlwIiksbD1udWxsLGI9bnVsbDtpZih0aGlzLmNvbmZpZy5sYWJlbHNFbmFibGVkKXtsZXQgZz12ZSh0aGlzLmNvbmZpZy5sYWJlbEJlZm9yZSx0aGlzLmNvbmZpZy5sYWJlbEFmdGVyLHRoaXMuY29uZmlnLmxhYmVsUG9zaXRpb24sdGhpcy5jb25maWcub3JpZW50YXRpb24pO2w9Zy5iZWZvcmUsYj1nLmFmdGVyLGUuYXBwZW5kKGwsYil9dGhpcy5lbGVtZW50cz17Y29udGFpbmVyOmUsdmlld3BvcnQ6byx3cmFwcGVyOm4sYmVmb3JlSW1hZ2U6cixhZnRlckltYWdlOmgsY2xpcDpzLGhhbmRsZTpmLGhhbmRsZUdyaXA6YSxsYWJlbEJlZm9yZTpsLGxhYmVsQWZ0ZXI6Yn19aW5pdE1vZHVsZXMoKXt0aGlzLnNsaWRlckdlc3R1cmVzPW5ldyBZKHRoaXMuZWxlbWVudHMuY29udGFpbmVyLHRoaXMuZWxlbWVudHMuaGFuZGxlLHRoaXMuY29uZmlnLm1vZGUsdGhpcy5jb25maWcub3JpZW50YXRpb24se29uUG9zaXRpb25DaGFuZ2U6ZT0+dGhpcy51cGRhdGVQb3NpdGlvbihlKSxvbkRyYWdTdGFydDooKT0+dGhpcy5vbkRyYWdTdGFydCgpLG9uRHJhZ0VuZDooKT0+dGhpcy5vbkRyYWdFbmQoKX0pLHRoaXMua2V5Ym9hcmRIYW5kbGVyPW5ldyBXKHRoaXMuZWxlbWVudHMuaGFuZGxlLHRoaXMuY29uZmlnLm9yaWVudGF0aW9uLHRoaXMuY29uZmlnLmtleWJvYXJkU3RlcCx0aGlzLmNvbmZpZy5rZXlib2FyZExhcmdlU3RlcCx0aGlzLmNvbmZpZy56b29tLHtvblBvc2l0aW9uQ2hhbmdlOmU9PnRoaXMudXBkYXRlUG9zaXRpb24oZSksZ2V0UG9zaXRpb246KCk9PnRoaXMuc3RhdGUucG9zaXRpb24sb25ab29tSW46KCk9Pnt2YXIgZTtyZXR1cm4oZT10aGlzLnpvb21QYW4pPT1udWxsP3ZvaWQgMDplLnpvb21JbigpfSxvblpvb21PdXQ6KCk9Pnt2YXIgZTtyZXR1cm4oZT10aGlzLnpvb21QYW4pPT1udWxsP3ZvaWQgMDplLnpvb21PdXQoKX0sb25ab29tUmVzZXQ6KCk9Pnt2YXIgZTtyZXR1cm4oZT10aGlzLnpvb21QYW4pPT1udWxsP3ZvaWQgMDplLnJlc2V0Wm9vbSgpfX0pLHRoaXMuY29uZmlnLnpvb20mJnRoaXMuaW5pdFpvb20oKSx0aGlzLmNvbmZpZy5mdWxsc2NyZWVuQnV0dG9uJiYodGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0taGFzLWZ1bGxzY3JlZW4iKSx0aGlzLmZ1bGxzY3JlZW5NYW5hZ2VyPW5ldyBfKHRoaXMuZWxlbWVudHMuY29udGFpbmVyLGU9Pnt0aGlzLnN0YXRlLmlzRnVsbHNjcmVlbj1lLE8odGhpcy5jb25maWcub25GdWxsc2NyZWVuQ2hhbmdlLGUpfSkpLHRoaXMuY29uZmlnLmFuaW1hdGVFbmFibGVkJiZ0aGlzLmluaXRFbnRyYW5jZUFuaW1hdGlvbigpLHRoaXMuY29uZmlnLmNsb3VkaW1hZ2UmJnRoaXMuaW5pdFJlc2l6ZU9ic2VydmVyKCl9aW5pdFpvb20oKXtpZih0aGlzLnpvb21QYW49bmV3IHRlKHRoaXMuZWxlbWVudHMudmlld3BvcnQsdGhpcy5lbGVtZW50cy5jb250YWluZXIsdGhpcy5jb25maWcsZT0+e3RoaXMuc3RhdGUuem9vbUxldmVsPWUsdGhpcy5zeW5jQ2xpcCgpLE8odGhpcy5jb25maWcub25ab29tLGUpfSwoKT0+dGhpcy5zeW5jQ2xpcCgpKSx0aGlzLmNvbmZpZy5zY3JvbGxIaW50JiYodGhpcy5zY3JvbGxIaW50PW5ldyBYKHRoaXMuZWxlbWVudHMuY29udGFpbmVyKSksdGhpcy56b29tR2VzdHVyZXM9bmV3IE4odGhpcy5lbGVtZW50cy5jb250YWluZXIsdGhpcy5lbGVtZW50cy5oYW5kbGUsdGhpcy56b29tUGFuLCgpPT57dmFyIGU7cmV0dXJuKGU9dGhpcy5zY3JvbGxIaW50KT09bnVsbD92b2lkIDA6ZS5zaG93KCl9KSx0aGlzLmNvbmZpZy56b29tQ29udHJvbHMpe2xldCBlPXBlKHRoaXMuY29uZmlnLnpvb21Db250cm9sc1Bvc2l0aW9uLHtvblpvb21JbjooKT0+e3ZhciB0O3JldHVybih0PXRoaXMuem9vbVBhbik9PW51bGw/dm9pZCAwOnQuem9vbUluKCl9LG9uWm9vbU91dDooKT0+e3ZhciB0O3JldHVybih0PXRoaXMuem9vbVBhbik9PW51bGw/dm9pZCAwOnQuem9vbU91dCgpfSxvblJlc2V0OigpPT57dmFyIHQ7cmV0dXJuKHQ9dGhpcy56b29tUGFuKT09bnVsbD92b2lkIDA6dC5yZXNldFpvb20oKX19KTt0aGlzLnpvb21Db250cm9sc0VsPWUuZWxlbWVudCx0aGlzLnpvb21Db250cm9sc0V2ZW50cz1lLmV2ZW50cyx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnpvb21Db250cm9sc0VsKSx0aGlzLmFwcGx5Wm9vbVBvc2l0aW9uQ2xhc3NlcygpfX1hcHBseVpvb21Qb3NpdGlvbkNsYXNzZXMoKXtsZXQgZT10aGlzLmNvbmZpZy56b29tQ29udHJvbHNQb3NpdGlvbjt0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKCJjaS1iZWZvcmUtYWZ0ZXItY29udGFpbmVyLS16b29tLXRvcC1yaWdodCIsZT09PSJ0b3AtcmlnaHQiKSx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKCJjaS1iZWZvcmUtYWZ0ZXItY29udGFpbmVyLS16b29tLXRvcCIsZS5zdGFydHNXaXRoKCJ0b3AtIikpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLXpvb20tbGVmdCIsZS5lbmRzV2l0aCgiLWxlZnQiKSl9aW5pdEVudHJhbmNlQW5pbWF0aW9uKCl7dGhpcy5hbmltVHJhbnNpdGlvblRpbWVyJiYoY2xlYXJUaW1lb3V0KHRoaXMuYW5pbVRyYW5zaXRpb25UaW1lciksdGhpcy5hbmltVHJhbnNpdGlvblRpbWVyPW51bGwsdGhpcy5lbGVtZW50cy5oYW5kbGUuc3R5bGUudHJhbnNpdGlvbj0iIix0aGlzLmVsZW1lbnRzLmNsaXAuc3R5bGUudHJhbnNpdGlvbj0iIik7bGV0IGU9MDt0aGlzLnN1cHByZXNzQ2FsbGJhY2tzPSEwLHRoaXMudXBkYXRlUG9zaXRpb24oZSksdGhpcy5zdXBwcmVzc0NhbGxiYWNrcz0hMSx0aGlzLmVudHJhbmNlQW5pbWF0aW9uPW5ldyBpZSh0aGlzLmVsZW1lbnRzLmNvbnRhaW5lcix0aGlzLmNvbmZpZy5hbmltYXRlRHVyYXRpb24sdGhpcy5jb25maWcuYW5pbWF0ZURlbGF5LHRoaXMuY29uZmlnLmFuaW1hdGVFYXNpbmcsdGhpcy5jb25maWcuYW5pbWF0ZU9uY2UsdD0+e2lmKHQ9PT0icmVzZXQiKXt0aGlzLmVsZW1lbnRzLmhhbmRsZS5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMuZWxlbWVudHMuY2xpcC5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMuc3VwcHJlc3NDYWxsYmFja3M9ITAsdGhpcy51cGRhdGVQb3NpdGlvbigwKSx0aGlzLnN1cHByZXNzQ2FsbGJhY2tzPSExLHRoaXMuZWxlbWVudHMuaGFuZGxlLm9mZnNldFdpZHRoO3JldHVybn10fHwodGhpcy5lbGVtZW50cy5oYW5kbGUuc3R5bGUudHJhbnNpdGlvbj1gbGVmdCAke3RoaXMuY29uZmlnLmFuaW1hdGVEdXJhdGlvbn1tcyAke3RoaXMuY29uZmlnLmFuaW1hdGVFYXNpbmd9LCB0b3AgJHt0aGlzLmNvbmZpZy5hbmltYXRlRHVyYXRpb259bXMgJHt0aGlzLmNvbmZpZy5hbmltYXRlRWFzaW5nfWAsdGhpcy5lbGVtZW50cy5jbGlwLnN0eWxlLnRyYW5zaXRpb249YGNsaXAtcGF0aCAke3RoaXMuY29uZmlnLmFuaW1hdGVEdXJhdGlvbn1tcyAke3RoaXMuY29uZmlnLmFuaW1hdGVFYXNpbmd9YCksdGhpcy5zdXBwcmVzc0NhbGxiYWNrcz0hMCx0aGlzLnVwZGF0ZVBvc2l0aW9uKHRoaXMuY29uZmlnLmluaXRpYWxQb3NpdGlvbiksdGhpcy5zdXBwcmVzc0NhbGxiYWNrcz0hMSx0fHwodGhpcy5hbmltVHJhbnNpdGlvblRpbWVyPXNldFRpbWVvdXQoKCk9Pnt0aGlzLmFuaW1UcmFuc2l0aW9uVGltZXI9bnVsbCx0aGlzLmVsZW1lbnRzLmhhbmRsZS5zdHlsZS50cmFuc2l0aW9uPSIiLHRoaXMuZWxlbWVudHMuY2xpcC5zdHlsZS50cmFuc2l0aW9uPSIifSx0aGlzLmNvbmZpZy5hbmltYXRlRHVyYXRpb24pKX0pfWxvYWRJbWFnZXMoKXtsZXQgZT10aGlzLnJlc29sdmVJbWFnZVNyYyh0aGlzLmNvbmZpZy5iZWZvcmVTcmMpLHQ9dGhpcy5yZXNvbHZlSW1hZ2VTcmModGhpcy5jb25maWcuYWZ0ZXJTcmMpO3RoaXMuY29uZmlnLmxhenlMb2FkJiZ0eXBlb2YgSW50ZXJzZWN0aW9uT2JzZXJ2ZXI8InUiPyh0aGlzLmxhenlMb2FkT2JzZXJ2ZXI9bmV3IEludGVyc2VjdGlvbk9ic2VydmVyKG89Pnt2YXIgbjtmb3IobGV0IHIgb2YgbylyLmlzSW50ZXJzZWN0aW5nJiYodGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZS5zcmM9ZSx0aGlzLmVsZW1lbnRzLmFmdGVySW1hZ2Uuc3JjPXQsKG49dGhpcy5sYXp5TG9hZE9ic2VydmVyKT09bnVsbHx8bi5kaXNjb25uZWN0KCksdGhpcy5sYXp5TG9hZE9ic2VydmVyPW51bGwpfSx7dGhyZXNob2xkOjB9KSx0aGlzLmxhenlMb2FkT2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1lbnRzLmNvbnRhaW5lcikpOih0aGlzLmVsZW1lbnRzLmJlZm9yZUltYWdlLnNyYz1lLHRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zcmM9dCksdGhpcy5yZWdpc3RlckltYWdlTG9hZEhhbmRsZXJzKCEwLCEwKX1yZWdpc3RlckltYWdlTG9hZEhhbmRsZXJzKGUsdCl7dGhpcy5pbWFnZUV2ZW50cy5kZXN0cm95KCk7bGV0IG89IWUsbj0hdCxyPSgpPT57byYmbiYmdGhpcy5vbkltYWdlc1JlYWR5KCl9LHM9KCk9PntvfHwobz0hMCxyKCkpfSxoPSgpPT57bnx8KG49ITAscigpKX0sZj0oKT0+e2NvbnNvbGUud2FybihgQ0lCZWZvcmVBZnRlcjogRmFpbGVkIHRvIGxvYWQgaW1hZ2UgIiR7dGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZS5zcmN9ImApLG98fChvPSEwLHIoKSl9LGE9KCk9Pntjb25zb2xlLndhcm4oYENJQmVmb3JlQWZ0ZXI6IEZhaWxlZCB0byBsb2FkIGltYWdlICIke3RoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zcmN9ImApLG58fChuPSEwLHIoKSl9O3RoaXMuaW1hZ2VFdmVudHMub24odGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZSwibG9hZCIscyksdGhpcy5pbWFnZUV2ZW50cy5vbih0aGlzLmVsZW1lbnRzLmFmdGVySW1hZ2UsImxvYWQiLGgpLHRoaXMuaW1hZ2VFdmVudHMub24odGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZSwiZXJyb3IiLGYpLHRoaXMuaW1hZ2VFdmVudHMub24odGhpcy5lbGVtZW50cy5hZnRlckltYWdlLCJlcnJvciIsYSksdGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZS5jb21wbGV0ZSYmdGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZS5zcmMmJnMoKSx0aGlzLmVsZW1lbnRzLmFmdGVySW1hZ2UuY29tcGxldGUmJnRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zcmMmJmgoKX1vbkltYWdlc1JlYWR5KCl7aWYodGhpcy5zdGF0ZS5pc1JlYWR5KXJldHVybjt0aGlzLnN0YXRlLmlzUmVhZHk9ITA7bGV0e25hdHVyYWxXaWR0aDplLG5hdHVyYWxIZWlnaHQ6dH09dGhpcy5lbGVtZW50cy5iZWZvcmVJbWFnZTtlJiZ0JiYodGhpcy5lbGVtZW50cy53cmFwcGVyLnN0eWxlLmFzcGVjdFJhdGlvPWAke2V9IC8gJHt0fWApLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1sb2FkaW5nIiksTyh0aGlzLmNvbmZpZy5vblJlYWR5KX1nZXRDbGlwWm9vbUluZm8oKXtpZighdGhpcy56b29tUGFufHx0aGlzLnpvb21QYW4uZ2V0Wm9vbSgpPD0xKXJldHVybjtsZXQgZT10aGlzLnpvb21QYW4uZ2V0UGFuKCksdD10aGlzLnpvb21QYW4uZ2V0Q29udGFpbmVyU2l6ZSgpO3JldHVybntsZXZlbDp0aGlzLnpvb21QYW4uZ2V0Wm9vbSgpLHBhblg6ZS54LHBhblk6ZS55LGNvbnRhaW5lcldpZHRoOnQud2lkdGgsY29udGFpbmVySGVpZ2h0OnQuaGVpZ2h0fX1zeW5jQ2xpcCgpe2VlKHRoaXMuZWxlbWVudHMuY2xpcCx0aGlzLnN0YXRlLnBvc2l0aW9uLHRoaXMuY29uZmlnLm9yaWVudGF0aW9uLHRoaXMuZ2V0Q2xpcFpvb21JbmZvKCkpfXVwZGF0ZVBvc2l0aW9uKGUpe3RoaXMuc3RhdGUucG9zaXRpb249YmUoZSksZWUodGhpcy5lbGVtZW50cy5jbGlwLHRoaXMuc3RhdGUucG9zaXRpb24sdGhpcy5jb25maWcub3JpZW50YXRpb24sdGhpcy5nZXRDbGlwWm9vbUluZm8oKSksX2UodGhpcy5lbGVtZW50cy5oYW5kbGUsdGhpcy5zdGF0ZS5wb3NpdGlvbix0aGlzLmNvbmZpZy5vcmllbnRhdGlvbiksc3QodGhpcy5lbGVtZW50cy5oYW5kbGUsdGhpcy5zdGF0ZS5wb3NpdGlvbikseWUodGhpcy5lbGVtZW50cy5sYWJlbEJlZm9yZSx0aGlzLmVsZW1lbnRzLmxhYmVsQWZ0ZXIsdGhpcy5zdGF0ZS5wb3NpdGlvbix0aGlzLmNvbmZpZy5vcmllbnRhdGlvbiksdGhpcy5zdXBwcmVzc0NhbGxiYWNrc3x8Tyh0aGlzLmNvbmZpZy5vblNsaWRlLHRoaXMuc3RhdGUucG9zaXRpb24pfW9uRHJhZ1N0YXJ0KCl7dGhpcy5zdGF0ZS5pc0RyYWdnaW5nPSEwLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLWRyYWdnaW5nIil9b25EcmFnRW5kKCl7dGhpcy5zdGF0ZS5pc0RyYWdnaW5nPSExLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLWRyYWdnaW5nIil9cmVzb2x2ZUltYWdlU3JjKGUpe2lmKHRoaXMuY29uZmlnLmNsb3VkaW1hZ2Upe2xldCB0PXRoaXMuZWxlbWVudHMuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRofHw4MDA7cmV0dXJuIFhlKGUsdCx0aGlzLmNvbmZpZy5jbG91ZGltYWdlKX1yZXR1cm4gZX1yZWJ1aWxkSGFuZGxlKCl7dmFyIGUsdDtsZXQgbz1kb2N1bWVudC5hY3RpdmVFbGVtZW50PT09dGhpcy5lbGVtZW50cy5oYW5kbGU7dGhpcy5lbGVtZW50cy5oYW5kbGUucmVtb3ZlKCk7bGV0IG49Z2UodGhpcy5jb25maWcuaGFuZGxlU3R5bGUsdGhpcy5jb25maWcub3JpZW50YXRpb24sdGhpcy5zdGF0ZS5wb3NpdGlvbik7dGhpcy5lbGVtZW50cy5jb250YWluZXIuYXBwZW5kQ2hpbGQobiksdGhpcy5lbGVtZW50cy5oYW5kbGU9bix0aGlzLmVsZW1lbnRzLmhhbmRsZUdyaXA9bi5xdWVyeVNlbGVjdG9yKCIuY2ktYmVmb3JlLWFmdGVyLWhhbmRsZS1ncmlwIiksKGU9dGhpcy5zbGlkZXJHZXN0dXJlcyk9PW51bGx8fGUuZGVzdHJveSgpLHRoaXMuc2xpZGVyR2VzdHVyZXM9bmV3IFkodGhpcy5lbGVtZW50cy5jb250YWluZXIsdGhpcy5lbGVtZW50cy5oYW5kbGUsdGhpcy5jb25maWcubW9kZSx0aGlzLmNvbmZpZy5vcmllbnRhdGlvbix7b25Qb3NpdGlvbkNoYW5nZTpyPT50aGlzLnVwZGF0ZVBvc2l0aW9uKHIpLG9uRHJhZ1N0YXJ0OigpPT50aGlzLm9uRHJhZ1N0YXJ0KCksb25EcmFnRW5kOigpPT50aGlzLm9uRHJhZ0VuZCgpfSksKHQ9dGhpcy5rZXlib2FyZEhhbmRsZXIpPT1udWxsfHx0LmRlc3Ryb3koKSx0aGlzLmtleWJvYXJkSGFuZGxlcj1uZXcgVyh0aGlzLmVsZW1lbnRzLmhhbmRsZSx0aGlzLmNvbmZpZy5vcmllbnRhdGlvbix0aGlzLmNvbmZpZy5rZXlib2FyZFN0ZXAsdGhpcy5jb25maWcua2V5Ym9hcmRMYXJnZVN0ZXAsdGhpcy5jb25maWcuem9vbSx7b25Qb3NpdGlvbkNoYW5nZTpyPT50aGlzLnVwZGF0ZVBvc2l0aW9uKHIpLGdldFBvc2l0aW9uOigpPT50aGlzLnN0YXRlLnBvc2l0aW9uLG9uWm9vbUluOigpPT57dmFyIHI7cmV0dXJuKHI9dGhpcy56b29tUGFuKT09bnVsbD92b2lkIDA6ci56b29tSW4oKX0sb25ab29tT3V0OigpPT57dmFyIHI7cmV0dXJuKHI9dGhpcy56b29tUGFuKT09bnVsbD92b2lkIDA6ci56b29tT3V0KCl9LG9uWm9vbVJlc2V0OigpPT57dmFyIHI7cmV0dXJuKHI9dGhpcy56b29tUGFuKT09bnVsbD92b2lkIDA6ci5yZXNldFpvb20oKX19KSx0aGlzLnpvb21HZXN0dXJlcyYmdGhpcy56b29tUGFuJiYodGhpcy56b29tR2VzdHVyZXMuZGVzdHJveSgpLHRoaXMuem9vbUdlc3R1cmVzPW5ldyBOKHRoaXMuZWxlbWVudHMuY29udGFpbmVyLHRoaXMuZWxlbWVudHMuaGFuZGxlLHRoaXMuem9vbVBhbiwoKT0+e3ZhciByO3JldHVybihyPXRoaXMuc2Nyb2xsSGludCk9PW51bGw/dm9pZCAwOnIuc2hvdygpfSkpLG8mJnRoaXMuZWxlbWVudHMuaGFuZGxlLmZvY3VzKCl9cmVidWlsZExhYmVscygpe3ZhciBlLHQ7aWYoKGU9dGhpcy5lbGVtZW50cy5sYWJlbEJlZm9yZSk9PW51bGx8fGUucmVtb3ZlKCksKHQ9dGhpcy5lbGVtZW50cy5sYWJlbEFmdGVyKT09bnVsbHx8dC5yZW1vdmUoKSx0aGlzLmVsZW1lbnRzLmxhYmVsQmVmb3JlPW51bGwsdGhpcy5lbGVtZW50cy5sYWJlbEFmdGVyPW51bGwsdGhpcy5jb25maWcubGFiZWxzRW5hYmxlZCl7bGV0IG89dmUodGhpcy5jb25maWcubGFiZWxCZWZvcmUsdGhpcy5jb25maWcubGFiZWxBZnRlcix0aGlzLmNvbmZpZy5sYWJlbFBvc2l0aW9uLHRoaXMuY29uZmlnLm9yaWVudGF0aW9uKTt0aGlzLmVsZW1lbnRzLmxhYmVsQmVmb3JlPW8uYmVmb3JlLHRoaXMuZWxlbWVudHMubGFiZWxBZnRlcj1vLmFmdGVyLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmFwcGVuZChvLmJlZm9yZSxvLmFmdGVyKSx5ZShvLmJlZm9yZSxvLmFmdGVyLHRoaXMuc3RhdGUucG9zaXRpb24sdGhpcy5jb25maWcub3JpZW50YXRpb24pfX1yZWJ1aWxkWm9vbSgpe3ZhciBlLHQsbyxuLHI7KGU9dGhpcy56b29tR2VzdHVyZXMpPT1udWxsfHxlLmRlc3Ryb3koKSx0aGlzLnpvb21HZXN0dXJlcz1udWxsLCh0PXRoaXMuc2Nyb2xsSGludCk9PW51bGx8fHQuZGVzdHJveSgpLHRoaXMuc2Nyb2xsSGludD1udWxsLChvPXRoaXMuem9vbUNvbnRyb2xzRXZlbnRzKT09bnVsbHx8by5kZXN0cm95KCksdGhpcy56b29tQ29udHJvbHNFdmVudHM9bnVsbCwobj10aGlzLnpvb21Db250cm9sc0VsKT09bnVsbHx8bi5yZW1vdmUoKSx0aGlzLnpvb21Db250cm9sc0VsPW51bGwsKHI9dGhpcy56b29tUGFuKT09bnVsbHx8ci5kZXN0cm95KCksdGhpcy56b29tUGFuPW51bGwsdGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZSgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0tem9vbS10b3AtcmlnaHQiKSx0aGlzLmVsZW1lbnRzLmNvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKCJjaS1iZWZvcmUtYWZ0ZXItY29udGFpbmVyLS16b29tLXRvcCIpLHRoaXMuZWxlbWVudHMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoImNpLWJlZm9yZS1hZnRlci1jb250YWluZXItLXpvb20tbGVmdCIpLHRoaXMuY29uZmlnLnpvb20mJnRoaXMuaW5pdFpvb20oKX1yZWJ1aWxkRnVsbHNjcmVlbigpe3ZhciBlOyhlPXRoaXMuZnVsbHNjcmVlbk1hbmFnZXIpPT1udWxsfHxlLmRlc3Ryb3koKSx0aGlzLmZ1bGxzY3JlZW5NYW5hZ2VyPW51bGwsdGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZSgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0taGFzLWZ1bGxzY3JlZW4iKSx0aGlzLmNvbmZpZy5mdWxsc2NyZWVuQnV0dG9uJiYodGhpcy5lbGVtZW50cy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgiY2ktYmVmb3JlLWFmdGVyLWNvbnRhaW5lci0taGFzLWZ1bGxzY3JlZW4iKSx0aGlzLmZ1bGxzY3JlZW5NYW5hZ2VyPW5ldyBfKHRoaXMuZWxlbWVudHMuY29udGFpbmVyLHQ9Pnt0aGlzLnN0YXRlLmlzRnVsbHNjcmVlbj10LE8odGhpcy5jb25maWcub25GdWxsc2NyZWVuQ2hhbmdlLHQpfSkpfWluaXRSZXNpemVPYnNlcnZlcigpe3R5cGVvZiBSZXNpemVPYnNlcnZlcj4idSJ8fCh0aGlzLnJlc2l6ZU9ic2VydmVyPW5ldyBSZXNpemVPYnNlcnZlcigoKT0+e3RoaXMucmVzaXplRGVib3VuY2VUaW1lciYmY2xlYXJUaW1lb3V0KHRoaXMucmVzaXplRGVib3VuY2VUaW1lciksdGhpcy5yZXNpemVEZWJvdW5jZVRpbWVyPXNldFRpbWVvdXQoKCk9PntpZih0aGlzLmNvbmZpZy5jbG91ZGltYWdlKXtsZXQgZT10aGlzLnJlc29sdmVJbWFnZVNyYyh0aGlzLmNvbmZpZy5iZWZvcmVTcmMpLHQ9dGhpcy5yZXNvbHZlSW1hZ2VTcmModGhpcy5jb25maWcuYWZ0ZXJTcmMpO3RoaXMuZWxlbWVudHMuYmVmb3JlSW1hZ2Uuc3JjIT09ZSYmKHRoaXMuZWxlbWVudHMuYmVmb3JlSW1hZ2Uuc3JjPWUpLHRoaXMuZWxlbWVudHMuYWZ0ZXJJbWFnZS5zcmMhPT10JiYodGhpcy5lbGVtZW50cy5hZnRlckltYWdlLnNyYz10KX10aGlzLnJlc2l6ZURlYm91bmNlVGltZXI9bnVsbH0sMjAwKX0pLHRoaXMucmVzaXplT2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1lbnRzLmNvbnRhaW5lcikpfX07ZnVuY3Rpb24gTyhpLC4uLmUpe2lmKGkpdHJ5e2koLi4uZSl9Y2F0Y2godCl7Y29uc29sZS5lcnJvcigiQ0lCZWZvcmVBZnRlcjogY2FsbGJhY2sgZXJyb3I6Iix0KX19ZnVuY3Rpb24gbHQoaSxlKXtpZihpPT09ZSlyZXR1cm4hMDtpZighaXx8IWUpcmV0dXJuITE7bGV0IHQ9T2JqZWN0LmtleXMoaSksbz1PYmplY3Qua2V5cyhlKTtpZih0Lmxlbmd0aCE9PW8ubGVuZ3RoKXJldHVybiExO2ZvcihsZXQgbiBvZiB0KWlmKGlbbl0hPT1lW25dKXJldHVybiExO3JldHVybiEwfXZhciBwPShpLGUsdCxvKT0+KHtrZXk6aSxuYW1lOmUsdHlwZTp7cHJpbWl0aXZlOiJzdHJpbmcifSxkZWZhdWx0OnQsZGVzY3JpcHRpb246b30pLEE9KGksZSx0LG8sbik9Pih7Li4ucChpLGUsdCxuKSx0eXBlOntwcmltaXRpdmU6InN0cmluZyIsc3BlY2lhbGl6ZWQ6InNlbGVjdCJ9LHNlbGVjdE9wdGlvbnNTdHJpbmc6by5tYXAocj0+QXJyYXkuaXNBcnJheShyKT9yLmpvaW4oIiA6ICIpOmAke3J9IDogJHtyfWApLmpvaW4oYApgKX0pLFQ9KGksZSx0LG8pPT5BKGksZSx0LHQ9PT0idHJ1ZSI/W1siT24iLCJ0cnVlIl0sWyJPZmYiLCJmYWxzZSJdXTpbWyJPZmYiLCJmYWxzZSJdLFsiT24iLCJ0cnVlIl1dLG8pLHplPShpLGUpPT4oey4uLnAoaSxlLCIiLCJDaG9vc2UgYSBXb3JkUHJlc3MgaW1hZ2Ugd2l0aCB0aGUgbmF0aXZlIE1lZGlhIHNlbGVjdG9yOyBJRHMgYXJlIHNpdGUtbG9jYWwuIiksdHlwZTp7cHJpbWl0aXZlOiJzdHJpbmciLHNwZWNpYWxpemVkOiJ3cE1lZGlhSWQifX0pLFI9KGksZSx0KT0+KHtrZXk6aSxuYW1lOmUsdHlwZTp7cHJpbWl0aXZlOiJvYmplY3QiLHNwZWNpYWxpemVkOiJncm91cCJ9LHByb3BlcnRpZXM6dCxkZXNjcmlwdGlvbjpgJHtlfSBzZXR0aW5ncy5gfSksY3Q9W1IoImNvbnRlbnQiLCJDb250ZW50IixbemUoImJlZm9yZUltYWdlIiwiQmVmb3JlIGltYWdlIikscCgiYmVmb3JlQWx0IiwiQmVmb3JlIGFsdCIsIiIsIkRlc2NyaWJlIHRoZSBiZWZvcmUgaW1hZ2U7IGVtcHR5IGV4cGxpY2l0bHkgbWVhbnMgZGVjb3JhdGl2ZS4iKSx6ZSgiYWZ0ZXJJbWFnZSIsIkFmdGVyIGltYWdlIikscCgiYWZ0ZXJBbHQiLCJBZnRlciBhbHQiLCIiLCJEZXNjcmliZSB0aGUgYWZ0ZXIgaW1hZ2U7IGVtcHR5IGV4cGxpY2l0bHkgbWVhbnMgZGVjb3JhdGl2ZS4iKSxUKCJzaG93TGFiZWxzIiwiU2hvdyBsYWJlbHMiLCJ0cnVlIiwiU2hvdyBib3RoIGVkaXRhYmxlIHNpZGUgbGFiZWxzLiIpLHAoImJlZm9yZUxhYmVsIiwiQmVmb3JlIGxhYmVsIiwiQmVmb3JlIiwiVmlzaWJsZSBiZWZvcmUgbGFiZWwuIikscCgiYWZ0ZXJMYWJlbCIsIkFmdGVyIGxhYmVsIiwiQWZ0ZXIiLCJWaXNpYmxlIGFmdGVyIGxhYmVsLiIpLEEoImxhYmVsUG9zaXRpb24iLCJMYWJlbCBwb3NpdGlvbiIsInRvcCIsW1siVG9wIiwidG9wIl0sWyJCb3R0b20iLCJib3R0b20iXV0sIk5hdGl2ZSBsYWJlbCBwb3NpdGlvbjsgaW4gdmVydGljYWwgbW9kZSB0aGVzZSBwbGFjZSBsYWJlbHMgbGVmdC9yaWdodC4iKV0pLFIoImNvbXBhcmlzb24iLCJDb21wYXJpc29uIixbQSgib3JpZW50YXRpb24iLCJPcmllbnRhdGlvbiIsImhvcml6b250YWwiLFtbIkhvcml6b250YWwiLCJob3Jpem9udGFsIl0sWyJWZXJ0aWNhbCIsInZlcnRpY2FsIl1dLCJEaXZpZGVyIG1vdmVtZW50IGF4aXMuIikscCgiaW5pdGlhbFBvc2l0aW9uIiwiSW5pdGlhbCBwb3NpdGlvbiAoJSkiLCI1MCIsIkNsYW1wIHRvIDBcdTIwMTMxMDA7IGludmFsaWQgdmFsdWVzIHVzZSA1MC4iKSxBKCJtb2RlIiwiSW50ZXJhY3Rpb24gbW9kZSIsImRyYWciLFtbIkRyYWciLCJkcmFnIl0sWyJDbGljayIsImNsaWNrIl0sWyJIb3ZlciIsImhvdmVyIl1dLCJEcmFnIHJlY29tbWVuZGVkOyBob3ZlciB0YXJnZXRzIGZpbmUtcG9pbnRlciBkZXZpY2VzLiBLZXlib2FyZCBhbHdheXMgd29ya3MuIiksQSgiaGFuZGxlU3R5bGUiLCJIYW5kbGUgc3R5bGUiLCJhcnJvd3MiLFtbIkFycm93cyIsImFycm93cyJdLFsiQ2lyY2xlIiwiY2lyY2xlIl0sWyJMaW5lIiwibGluZSJdXSwiTmF0aXZlIGhhbmRsZSBhcHBlYXJhbmNlLiIpLEEoImFzcGVjdFJhdGlvIiwiVmlld3BvcnQgcmF0aW8iLCI0IC8gMyIsWyI0IC8gMyIsIjE2IC8gOSIsIjEgLyAxIiwiMyAvIDQiLFsiQ3VzdG9tIiwiY3VzdG9tIl1dLCJDaG9vc2UgYSBwcmVzZXQgb3IgQ3VzdG9tIHRvIHVzZSBDdXN0b20gdmlld3BvcnQgcmF0aW8uIikscCgiY3VzdG9tQXNwZWN0UmF0aW8iLCJDdXN0b20gdmlld3BvcnQgcmF0aW8iLCI0IC8gMyIsIlVzZWQgd2hlbiBWaWV3cG9ydCByYXRpbyBpcyBDdXN0b20uIEVudGVyIHdpZHRoIC8gaGVpZ2h0LCBlLmcuIDIxIC8gOSwgb3IgYSBkZWNpbWFsLCBlLmcuIDEuODUuIFBvc2l0aXZlIG51bWJlcnMgb25seTsgaW52YWxpZCB2YWx1ZXMgdXNlIDQgLyAzLiIpLEEoIm9iamVjdEZpdCIsIkltYWdlIGZpdCIsImNvdmVyIixbWyJDb3ZlciAoY3JvcCB0byBmaWxsKSIsImNvdmVyIl0sWyJDb250YWluIChzaG93IHdob2xlIGltYWdlKSIsImNvbnRhaW4iXV0sIkJvdGggaW1hZ2VzIHNoYXJlIHRoZSBzYW1lIGZpdHRpbmcgc3RyYXRlZ3kuIildKSxSKCJhbmltYXRpb24iLCJFbnRyYW5jZSBhbmltYXRpb24iLFtUKCJlbmFibGVkIiwiRW50cmFuY2UgYW5pbWF0aW9uIiwiZmFsc2UiLCJPcHRpb25hbCBuYXRpdmUgZWFzZS1vdXQgZW50cmFuY2U7IGRpc2FibGVkIGZvciByZWR1Y2VkIG1vdGlvbi4iKSxwKCJkdXJhdGlvbiIsIkR1cmF0aW9uIChtcykiLCI4MDAiLCIwXHUyMDEzMTAwMDAgbWlsbGlzZWNvbmRzLiIpLHAoImRlbGF5IiwiRGVsYXkgKG1zKSIsIjAiLCIwXHUyMDEzMTAwMDAgbWlsbGlzZWNvbmRzLiIpLFQoIm9uY2UiLCJBbmltYXRlIG9uY2UiLCJ0cnVlIiwiVXNlIHRoZSBuYXRpdmUgYW5pbWF0ZU9uY2Ugb3B0aW9uLiIpXSksUigiem9vbSIsIlpvb20gYW5kIHBhbiIsW1QoImVuYWJsZWQiLCJFbmFibGUgem9vbSIsImZhbHNlIiwiTmF0aXZlIHpvb20vcGFuLCBrZXlib2FyZCBzaG9ydGN1dHMgYW5kIHBpbmNoIGdlc3R1cmVzLiIpLHAoIm1heGltdW0iLCJNYXhpbXVtIHpvb20iLCI0IiwiQ2xhbXAgdG8gMVx1MjAxMzEwOyBpbnZhbGlkIHZhbHVlcyB1c2UgNC4iKSxUKCJjb250cm9scyIsIlNob3cgem9vbSBjb250cm9scyIsInRydWUiLCJTaG93IG5hdGl2ZSBidXR0b25zIHdoZW4gem9vbSBpcyBlbmFibGVkLiIpLEEoImNvbnRyb2xzUG9zaXRpb24iLCJab29tIGNvbnRyb2xzIHBvc2l0aW9uIiwiYm90dG9tLXJpZ2h0IixbWyJCb3R0b20gcmlnaHQiLCJib3R0b20tcmlnaHQiXSxbIkJvdHRvbSBjZW50ZXIiLCJib3R0b20tY2VudGVyIl0sWyJCb3R0b20gbGVmdCIsImJvdHRvbS1sZWZ0Il0sWyJUb3AgcmlnaHQiLCJ0b3AtcmlnaHQiXSxbIlRvcCBjZW50ZXIiLCJ0b3AtY2VudGVyIl0sWyJUb3AgbGVmdCIsInRvcC1sZWZ0Il1dLCJOYXRpdmUgY29udHJvbCBwb3NpdGlvbi4iKSxUKCJzY3JvbGxIaW50IiwiU2hvdyBzY3JvbGwgaGludCIsInRydWUiLCJTaG93IHRoZSBsb2NhbGl6ZWQgbmF0aXZlIHNjcm9sbCBoaW50IHdoZW4gem9vbSBpcyBlbmFibGVkLiIpXSksVCgiZnVsbHNjcmVlbiIsIkVuYWJsZSBmdWxsc2NyZWVuIGJ1dHRvbiIsImZhbHNlIiwiTmF0aXZlIGJyb3dzZXIgZnVsbHNjcmVlbiB3aGVyZSBzdXBwb3J0ZWQ7IGZyb250ZW5kIG9ubHkuIiksUigicGVyZm9ybWFuY2UiLCJQZXJmb3JtYW5jZSIsW0EoImxvYWRpbmciLCJJbWFnZSBsb2FkaW5nIiwibGF6eSIsW1siTGF6eSIsImxhenkiXSxbIkVhZ2VyIChhYm92ZSB0aGUgZm9sZCkiLCJlYWdlciJdXSwiTmF0aXZlIER5bmFtaWMgSW1hZ2UgbG9hZGluZyBvd25zIGxhemluZXNzOyB2ZW5kb3IgbGF6eUxvYWQgaXMgZGlzYWJsZWQuIiksQSgiaW1hZ2VTaXplIiwiSW1hZ2Ugc2l6ZSIsImZ1bGwiLFtbIkZ1bGwgKG9yaWdpbmFsIHVwbG9hZCkiLCJmdWxsIl0sWyIyMDQ4IHB4IiwiMjA0OHgyMDQ4Il0sWyIxNTM2IHB4IiwiMTUzNngxNTM2Il0sWyJMYXJnZSAoMTAyNCBweCkiLCJsYXJnZSJdLFsiTWVkaXVtIGxhcmdlICg3NjggcHgpIiwibWVkaXVtX2xhcmdlIl0sWyJNZWRpdW0gKDMwMCBweCkiLCJtZWRpdW0iXV0sIldvcmRQcmVzcyBzaXplIGxvYWRlZCBmb3IgYm90aCBpbWFnZXMuIFBpY2sgdGhlIHNtYWxsZXN0IHRoYXQgc3RheXMgc2hhcnAgYXQgdGhlIGRpc3BsYXllZCB3aWR0aDsgc2l6ZXMgZm9sbG93IFNldHRpbmdzIFx1MjE5MiBNZWRpYSwgYW5kIGFuIGltYWdlIHNtYWxsZXIgdGhhbiB0aGUgc2l6ZSBsb2FkcyBpdHMgb3JpZ2luYWwuIildKSxSKCJhY2Nlc3NpYmlsaXR5IiwiQWNjZXNzaWJsZSBuYW1lcyBhbmQgdHJhbnNsYXRpb25zIixbcCgiY29tcGFyaXNvbkxhYmVsIiwiQ29tcGFyaXNvbiBuYW1lIiwiQmVmb3JlIGFuZCBhZnRlciBpbWFnZSBjb21wYXJpc29uIiwiQWNjZXNzaWJsZSBuYW1lIG9mIHRoZSBuYXRpdmUgY29tcGFyaXNvbiBncm91cC4iKSxwKCJzbGlkZXJMYWJlbCIsIlNsaWRlciBuYW1lIGFuZCBpbnN0cnVjdGlvbnMiLCJJbWFnZSBjb21wYXJpc29uIGRpdmlkZXIiLCJBY2Nlc3NpYmxlIG5hbWUgb2YgdGhlIGRpdmlkZXIgc2xpZGVyLiBTY3JlZW4gcmVhZGVycyBzYXkgaG93IHRvIGFkanVzdCBhIHNsaWRlcjsgYWRkZWQgaW5zdHJ1Y3Rpb25zIG11c3Qgbm90IG1lbnRpb24ga2V5cyBvbmx5LiIpLHAoInpvb21JbkxhYmVsIiwiWm9vbSBpbiIsIlpvb20gaW4iLCJab29tLWluIGJ1dHRvbiBuYW1lLiIpLHAoInpvb21PdXRMYWJlbCIsIlpvb20gb3V0IiwiWm9vbSBvdXQiLCJab29tLW91dCBidXR0b24gbmFtZS4iKSxwKCJyZXNldFpvb21MYWJlbCIsIlJlc2V0IHpvb20iLCJSZXNldCB6b29tIiwiUmVzZXQgYnV0dG9uIG5hbWUuIikscCgicGFuTGVmdExhYmVsIiwiTW92ZSBpbWFnZSBsZWZ0IiwiTW92ZSBpbWFnZSBsZWZ0IiwiTmFtZSBvZiB0aGUgbGVmdCBwYW4gYnV0dG9uOyBBbHQrTGVmdCBhbHNvIG1vdmVzIHRoZSB6b29tZWQgaW1hZ2UuIikscCgicGFuUmlnaHRMYWJlbCIsIk1vdmUgaW1hZ2UgcmlnaHQiLCJNb3ZlIGltYWdlIHJpZ2h0IiwiTmFtZSBvZiB0aGUgcmlnaHQgcGFuIGJ1dHRvbjsgQWx0K1JpZ2h0IGFsc28gbW92ZXMgdGhlIHpvb21lZCBpbWFnZS4iKSxwKCJwYW5VcExhYmVsIiwiTW92ZSBpbWFnZSB1cCIsIk1vdmUgaW1hZ2UgdXAiLCJOYW1lIG9mIHRoZSB1cCBwYW4gYnV0dG9uOyBBbHQrVXAgYWxzbyBtb3ZlcyB0aGUgem9vbWVkIGltYWdlLiIpLHAoInBhbkRvd25MYWJlbCIsIk1vdmUgaW1hZ2UgZG93biIsIk1vdmUgaW1hZ2UgZG93biIsIk5hbWUgb2YgdGhlIGRvd24gcGFuIGJ1dHRvbjsgQWx0K0Rvd24gYWxzbyBtb3ZlcyB0aGUgem9vbWVkIGltYWdlLiIpLHAoImVudGVyRnVsbHNjcmVlbkxhYmVsIiwiRW50ZXIgZnVsbHNjcmVlbiIsIkVudGVyIGZ1bGxzY3JlZW4iLCJGdWxsc2NyZWVuIGVudHJ5IG5hbWUuIikscCgiZXhpdEZ1bGxzY3JlZW5MYWJlbCIsIkV4aXQgZnVsbHNjcmVlbiIsIkV4aXQgZnVsbHNjcmVlbiIsIkZ1bGxzY3JlZW4gZXhpdCBuYW1lLiIpLHAoInNjcm9sbEhpbnRUZXh0IiwiU2Nyb2xsIGhpbnQiLCJDdHJsIC8gXHUyMzE4ICsgc2Nyb2xsIG9yIHBpbmNoIHRvIHpvb20iLCJWaXNpYmxlIHpvb20gaGludCB0ZXh0LiIpXSldLG9lPWN0LmZsYXRNYXAoaT0+aS5wcm9wZXJ0aWVzP2kucHJvcGVydGllcy5tYXAoZT0+KHsuLi5lLHBhdGg6YCR7aS5rZXl9LiR7ZS5rZXl9YH0pKTpbey4uLmkscGF0aDppLmtleX1dKSxuZT1PYmplY3QuZnJvbUVudHJpZXMob2UubWFwKGk9PltpLnBhdGgsaS5kZWZhdWx0XSkpLHJlPWk9PiJkYXRhLWVkLWJhLSIraS5yZXBsYWNlQWxsKCIuIiwiLSIpLnJlcGxhY2UoL1tBLVpdL2csZT0+Ii0iK2UudG9Mb3dlckNhc2UoKSksaHQ9aT0+L14oY29udGVudFwuKGJlZm9yZUltYWdlfGFmdGVySW1hZ2V8YmVmb3JlQWx0fGFmdGVyQWx0KXxwZXJmb3JtYW5jZVwuaW1hZ2VTaXplKSQvLnRlc3QoaSksc2U9b2UuZmlsdGVyKGk9PiFodChpLnBhdGgpKTtmdW5jdGlvbiBrZShpKXtyZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKHNlLm1hcChlPT5bZS5wYXRoLGkuZ2V0QXR0cmlidXRlKHJlKGUucGF0aCkpPz9lLmRlZmF1bHRdKSl9ZnVuY3Rpb24gVShpLGUsdCxvKXtsZXQgbj10eXBlb2YgaT09Im51bWJlciJ8fHR5cGVvZiBpPT0ic3RyaW5nIiYmaS50cmltKCk/TnVtYmVyKGkpOk5hTjtyZXR1cm4gTnVtYmVyLmlzRmluaXRlKG4pP01hdGgubWF4KHQsTWF0aC5taW4obyxuKSk6ZX1mdW5jdGlvbiBmdChpKXtsZXQgZT1TdHJpbmcoaT8/IiIpLnRyaW0oKS5tYXRjaCgvXihcZCsoPzpcLlxkKyk/fFwuXGQrKSg/OlxzKlwvXHMqKFxkKyg/OlwuXGQrKT98XC5cZCspKT8kLyk7aWYoIWUpcmV0dXJuIjQgLyAzIjtsZXQgdD1OdW1iZXIoZVsxXSksbz1OdW1iZXIoZVsyXT8/MSksbj10L287cmV0dXJuW3QsbyxuXS5ldmVyeShyPT5OdW1iZXIuaXNGaW5pdGUocikmJnI+MCk/YCR7dH0gLyAke299YDoiNCAvIDMifWZ1bmN0aW9uIENlKGk9e30sZT0hMSl7bGV0IHQ9ey4uLm5lLC4uLml9LG89cj0+e2xldCBzPW9lLmZpbmQoaD0+aC5wYXRoPT09cik7cmV0dXJuIHMuc2VsZWN0T3B0aW9uc1N0cmluZy5zcGxpdChgCmApLm1hcChoPT5oLnNwbGl0KCIgOiAiKVsxXSkuaW5jbHVkZXModFtyXSk/dFtyXTpzLmRlZmF1bHR9LG49cj0+byhyKT09PSJ0cnVlIjtyZXR1cm57b3JpZW50YXRpb246bygiY29tcGFyaXNvbi5vcmllbnRhdGlvbiIpLGluaXRpYWxQb3NpdGlvbjpVKHRbImNvbXBhcmlzb24uaW5pdGlhbFBvc2l0aW9uIl0sNTAsMCwxMDApLG1vZGU6bygiY29tcGFyaXNvbi5tb2RlIiksaGFuZGxlU3R5bGU6bygiY29tcGFyaXNvbi5oYW5kbGVTdHlsZSIpLGxhYmVsczpuKCJjb250ZW50LnNob3dMYWJlbHMiKT97YmVmb3JlOlN0cmluZyh0WyJjb250ZW50LmJlZm9yZUxhYmVsIl0pLGFmdGVyOlN0cmluZyh0WyJjb250ZW50LmFmdGVyTGFiZWwiXSl9OiExLGxhYmVsUG9zaXRpb246bygiY29udGVudC5sYWJlbFBvc2l0aW9uIiksYXNwZWN0UmF0aW86bygiY29tcGFyaXNvbi5hc3BlY3RSYXRpbyIpPT09ImN1c3RvbSI/ZnQodFsiY29tcGFyaXNvbi5jdXN0b21Bc3BlY3RSYXRpbyJdKTpvKCJjb21wYXJpc29uLmFzcGVjdFJhdGlvIiksYW5pbWF0ZTpuKCJhbmltYXRpb24uZW5hYmxlZCIpJiYhZT97ZHVyYXRpb246VSh0WyJhbmltYXRpb24uZHVyYXRpb24iXSw4MDAsMCwxZTQpLGRlbGF5OlUodFsiYW5pbWF0aW9uLmRlbGF5Il0sMCwwLDFlNCksZWFzaW5nOiJlYXNlLW91dCJ9OiExLGFuaW1hdGVPbmNlOm4oImFuaW1hdGlvbi5vbmNlIiksem9vbTpuKCJ6b29tLmVuYWJsZWQiKSx6b29tTWF4OlUodFsiem9vbS5tYXhpbXVtIl0sNCwxLDEwKSx6b29tQ29udHJvbHM6bigiem9vbS5lbmFibGVkIikmJm4oInpvb20uY29udHJvbHMiKSx6b29tQ29udHJvbHNQb3NpdGlvbjpvKCJ6b29tLmNvbnRyb2xzUG9zaXRpb24iKSxzY3JvbGxIaW50Om4oInpvb20uZW5hYmxlZCIpJiZuKCJ6b29tLnNjcm9sbEhpbnQiKSxmdWxsc2NyZWVuQnV0dG9uOm4oImZ1bGxzY3JlZW4iKSxsYXp5TG9hZDohMSxrZXlib2FyZFN0ZXA6MSxrZXlib2FyZExhcmdlU3RlcDoxMCx0aGVtZToibGlnaHQifX1mdW5jdGlvbiB4ZShpLGUpe3RyeXtsZXQgdD1uZXcgVVJMKGksZSk7cmV0dXJuIGkmJlsiaHR0cDoiLCJodHRwczoiXS5pbmNsdWRlcyh0LnByb3RvY29sKT90LmhyZWY6bnVsbH1jYXRjaHtyZXR1cm4gbnVsbH19ZnVuY3Rpb24gUGUoaSxlKXtsZXQgdD1lLmdldEVsZW1lbnRzKCksbz10LmNvbnRhaW5lcixuPVsuLi5vLnF1ZXJ5U2VsZWN0b3JBbGwoIi5jaS1iZWZvcmUtYWZ0ZXItbGFiZWwiKV0scj10LmhhbmRsZS5xdWVyeVNlbGVjdG9yKCIuY2ktYmVmb3JlLWFmdGVyLWhhbmRsZS1ncmlwIikscz1bLi4uby5xdWVyeVNlbGVjdG9yQWxsKCIuY2ktYmVmb3JlLWFmdGVyLXpvb20tY29udHJvbHMsIC5jaS1iZWZvcmUtYWZ0ZXItZnVsbHNjcmVlbi1idG4sIC5lZC1iZWZvcmUtYWZ0ZXJfX3Bhbi1jb250cm9scyIpXSxoPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpO2guY2xhc3NOYW1lPSJlZC1iZWZvcmUtYWZ0ZXJfX2RvY2siO2xldCBmPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpO2YuY2xhc3NOYW1lPSJlZC1iZWZvcmUtYWZ0ZXJfX2xhYmVsLWRvY2siO2xldCBhPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpO2EuY2xhc3NOYW1lPSJlZC1iZWZvcmUtYWZ0ZXJfX2NvbnRyb2wtZG9jayIsaC5hcHBlbmQoZixhKSxoLmhpZGRlbj0hMCxpLmFwcGVuZChoKTtsZXQgbD1uZXcgQWJvcnRDb250cm9sbGVyLGI9MCxnPSExLHc9Yz0+Yy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSx4PShjLG0pPT5jLmxlZnQ8bS5sZWZ0LTF8fGMucmlnaHQ+bS5yaWdodCsxfHxjLnRvcDxtLnRvcC0xfHxjLmJvdHRvbT5tLmJvdHRvbSsxLHo9KGMsbSk9PmMubGVmdDxtLnJpZ2h0KzImJmMucmlnaHQ+bS5sZWZ0LTImJmMudG9wPG0uYm90dG9tKzImJmMuYm90dG9tPm0udG9wLTIsTT1jPT4hYy5oaWRkZW4mJmdldENvbXB1dGVkU3R5bGUoYykuZGlzcGxheSE9PSJub25lIjtmdW5jdGlvbiBJKCl7aWYoYj0wLGd8fCFpLmlzQ29ubmVjdGVkKXJldHVybjtsZXQgYz1kb2N1bWVudC5hY3RpdmVFbGVtZW50LG09Wy4uLm4sLi4uc10uc29tZShDPT5DPT09Y3x8Qy5jb250YWlucyhjKSk7Zm9yKGxldCBDIG9mWy4uLm4sLi4uc10pQy5wYXJlbnRFbGVtZW50IT09byYmby5hcHBlbmQoQyk7aC5oaWRkZW49ITAsZi5oaWRkZW49ITAsYS5oaWRkZW49ITA7bGV0IGs9dyhvKTtpZihrLndpZHRoJiZrLmhlaWdodCl7bGV0IEM9dyhyfHx0LmhhbmRsZSksSD10LmhhbmRsZS5nZXRBdHRyaWJ1dGUoImFyaWEtb3JpZW50YXRpb24iKT09PSJ2ZXJ0aWNhbCI/e2xlZnQ6Qy5sZWZ0LHJpZ2h0OkMucmlnaHQsdG9wOmsudG9wLGJvdHRvbTprLmJvdHRvbX06e2xlZnQ6ay5sZWZ0LHJpZ2h0OmsucmlnaHQsdG9wOkMudG9wLGJvdHRvbTpDLmJvdHRvbX0sJD1zLmZpbHRlcihNKS5tYXAodyksRz0kLnNvbWUoTD0+eChMLGspfHx6KEwsSCkpfHwkLnNvbWUoKEwsQik9PiQuc2xpY2UoQisxKS5zb21lKEo9PnooTCxKKSkpLFY9bi5tYXAodyksZmU9Vi5zb21lKEw9PngoTCxrKXx8eihMLEgpfHwhRyYmJC5zb21lKEI9PnooTCxCKSkpfHxWLnNvbWUoKEwsQik9PlYuc2xpY2UoQisxKS5zb21lKEo9PnooTCxKKSkpO2ZlJiYoZi5hcHBlbmQoLi4ubiksZi5oaWRkZW49ITEpLEcmJihhLmFwcGVuZCguLi5zKSxhLmhpZGRlbj0hMSksaC5oaWRkZW49IWZlJiYhR31tJiZjLmlzQ29ubmVjdGVkJiZNKGMpJiZjLmZvY3VzKHtwcmV2ZW50U2Nyb2xsOiEwfSl9ZnVuY3Rpb24gUCgpeyFnJiYhYiYmKGI9cmVxdWVzdEFuaW1hdGlvbkZyYW1lKEkpKX1sZXQgRj1uZXcgUmVzaXplT2JzZXJ2ZXIoUCk7Zm9yKGxldCBjIG9mW2ksbywuLi5uLC4uLnNdKUYub2JzZXJ2ZShjKTtsZXQgZD1uZXcgTXV0YXRpb25PYnNlcnZlcihQKTtmb3IobGV0IGM9aTtjO2M9Yy5wYXJlbnRFbGVtZW50KWQub2JzZXJ2ZShjLHthdHRyaWJ1dGVzOiEwLGF0dHJpYnV0ZUZpbHRlcjpbImNsYXNzIiwic3R5bGUiXX0pO3dpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLFAse3NpZ25hbDpsLnNpZ25hbH0pLGRvY3VtZW50LmZvbnRzPy5hZGRFdmVudExpc3RlbmVyKCJsb2FkaW5nZG9uZSIsUCx7c2lnbmFsOmwuc2lnbmFsfSksZG9jdW1lbnQuZm9udHM/LnJlYWR5LnRoZW4oUCk7ZnVuY3Rpb24gdSgpe2c9ITAsY2FuY2VsQW5pbWF0aW9uRnJhbWUoYiksRi5kaXNjb25uZWN0KCksZC5kaXNjb25uZWN0KCksbC5hYm9ydCgpO2ZvcihsZXQgYyBvZlsuLi5uLC4uLnNdKWMucGFyZW50RWxlbWVudCE9PW8mJm8uYXBwZW5kKGMpO2gucmVtb3ZlKCl9dHJ5e0koKX1jYXRjaChjKXt0aHJvdyB1KCksY31yZXR1cm57cmVmcmVzaDpQLGRpc3Bvc2U6dX19dmFyIGR0PVN5bWJvbC5mb3IoImVkLmJlZm9yZS1hZnRlci52MSIpLEQ9Ii5lZC1iZWZvcmUtYWZ0ZXJbZGF0YS1lZC1iZWZvcmUtYWZ0ZXJdIixTPW5ldyBNYXAsTGU9bWF0Y2hNZWRpYSgiKHByZWZlcnMtcmVkdWNlZC1tb3Rpb246IHJlZHVjZSkiKSxtdD17ZmFsbGJhY2s6IjpzY29wZSA+IC5lZC1iZWZvcmUtYWZ0ZXJfX2ZhbGxiYWNrIixtb3VudDoiOnNjb3BlID4gLmVkLWJlZm9yZS1hZnRlcl9fbW91bnQifSxLPShpLGUpPT5pLnF1ZXJ5U2VsZWN0b3IobXRbZV0pLGFlPWk9Pmk/Lm5vZGVUeXBlPT09MSxsZT1uZXcgTWFwO2Z1bmN0aW9uIHV0KGksZSl7bGV0IHQ9aS5jbG9zZXN0KCJbbGFuZ10iKT8uZ2V0QXR0cmlidXRlKCJsYW5nIil8fCIiO2lmKCFsZS5oYXModCkpe2xldCBvO3RyeXtvPW5ldyBJbnRsLk51bWJlckZvcm1hdCh0fHx2b2lkIDAse3N0eWxlOiJwZXJjZW50IixtYXhpbXVtRnJhY3Rpb25EaWdpdHM6MH0pfWNhdGNoe289bmV3IEludGwuTnVtYmVyRm9ybWF0KHZvaWQgMCx7c3R5bGU6InBlcmNlbnQiLG1heGltdW1GcmFjdGlvbkRpZ2l0czowfSl9bGUuc2V0KHQsbyl9cmV0dXJuIGxlLmdldCh0KS5mb3JtYXQoZS8xMDApfWZ1bmN0aW9uIEFlKGksZT0hMSl7bGV0IHQ9SyhpLCJmYWxsYmFjayIpLG89SyhpLCJtb3VudCIpO2lmKCF0fHwhbylyZXR1cm47bGV0IG49Wy4uLnQucXVlcnlTZWxlY3RvckFsbCgiaW1nIildLHI9a2UoaSkscz1DZShyLExlLm1hdGNoZXN8fGUpO2kuaGFzQXR0cmlidXRlKCJkYXRhLWV0Y2gtaGFzLWN1c3RvbS1jbGFzc2VzIik/by5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1fZWQtYmEtcmF0aW8iLHMuYXNwZWN0UmF0aW8pOih0LnN0eWxlLmFzcGVjdFJhdGlvPXMuYXNwZWN0UmF0aW8saS5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1fZWQtYmEtcmF0aW8iLHMuYXNwZWN0UmF0aW8pKTtsZXQgaD1uZXcgQWJvcnRDb250cm9sbGVyLGY9T2JqZWN0LmZyb21FbnRyaWVzKFsicm9sZSIsImFyaWEtbGFiZWwiLCJhcmlhLWxhYmVsbGVkYnkiXS5tYXAoZD0+W2QsaS5nZXRBdHRyaWJ1dGUoZCldKSksYT17ZmFsbGJhY2s6dCxtb3VudDpvLGltYWdlczpuLGlucHV0OnIsY2ZnOnMsdXNlck1vdmVkOiExLGluc3RhbmNlOm51bGwsbGF5b3V0Om51bGwscGFuQ29udHJvbHM6bnVsbCxkaXNwb3NlOkYsZW5oYW5jZTpQfTtTLnNldChpLGEpLGkucmVtb3ZlQXR0cmlidXRlKCJkYXRhLWVkLWJhLXJlYWR5Iiksby5oaWRkZW49ITA7bGV0IGw9ZD0+U3RyaW5nKHJbImFjY2Vzc2liaWxpdHkuIitkXT8/IiIpLnRyaW0oKXx8bmVbImFjY2Vzc2liaWxpdHkuIitkXTtmdW5jdGlvbiBiKCl7Zm9yKGxldFtkLHVdb2YgT2JqZWN0LmVudHJpZXMoZikpdT09PW51bGw/aS5yZW1vdmVBdHRyaWJ1dGUoZCk6aS5zZXRBdHRyaWJ1dGUoZCx1KX1mdW5jdGlvbiBnKCl7IWEuaW5zdGFuY2V8fGEudXNlck1vdmVkfHwoYS51c2VyTW92ZWQ9ITAsYS5pbnN0YW5jZS5jYW5jZWxFbnRyYW5jZSgpKX1mdW5jdGlvbiB3KCl7aWYoYS5wYW5Db250cm9scyYmYS5pbnN0YW5jZSl7bGV0IGQ9YS5pbnN0YW5jZS5nZXRab29tKCk8PTE7ZCYmYS5wYW5Db250cm9scy5jb250YWlucyhkb2N1bWVudC5hY3RpdmVFbGVtZW50KSYmYS5pbnN0YW5jZS5nZXRFbGVtZW50cygpLmhhbmRsZS5mb2N1cyh7cHJldmVudFNjcm9sbDohMH0pLGEucGFuQ29udHJvbHMuaGlkZGVuPWR9YS5sYXlvdXQ/LnJlZnJlc2goKX1mdW5jdGlvbiB4KGQpe2lmKCFhLmluc3RhbmNlfHxhLmluc3RhbmNlLmdldFpvb20oKTw9MSlyZXR1cm47ZygpO2xldHt3aWR0aDp1LGhlaWdodDpjfT1hLmluc3RhbmNlLmdldEVsZW1lbnRzKCkuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFttLGtdPXtsZWZ0OlstdS8xMCwwXSxyaWdodDpbdS8xMCwwXSx1cDpbMCwtYy8xMF0sZG93bjpbMCxjLzEwXX1bZF07YS5pbnN0YW5jZS5wYW5CeShtLGspfWZ1bmN0aW9uIHooKXtpZighcy56b29tKXJldHVybjtsZXQgZD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTtkLmNsYXNzTmFtZT0iZWQtYmVmb3JlLWFmdGVyX19wYW4tY29udHJvbHMiLGQuaGlkZGVuPSEwO2ZvcihsZXRbdSxjXW9mIE9iamVjdC5lbnRyaWVzKHtsZWZ0OiJtMTQgNi02IDYgNiA2TTggMTJoMTIiLHJpZ2h0OiJtMTAgNiA2IDYtNiA2TTQgMTJoMTIiLHVwOiJtNiAxNCA2LTYgNiA2TTEyIDh2MTIiLGRvd246Im02IDEwIDYgNiA2LTZNMTIgNHYxMiJ9KSl7bGV0IG09ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYnV0dG9uIik7bS50eXBlPSJidXR0b24iLG0uY2xhc3NOYW1lPSJlZC1iZWZvcmUtYWZ0ZXJfX3Bhbi1idXR0b24iLG0uZGF0YXNldC5lZEJhUGFuPXUsbS5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLGwoInBhbiIrdVswXS50b1VwcGVyQ2FzZSgpK3Uuc2xpY2UoMSkrIkxhYmVsIikpLG0uc2V0QXR0cmlidXRlKCJhcmlhLWtleXNob3J0Y3V0cyIsIkFsdCtBcnJvdyIrdVswXS50b1VwcGVyQ2FzZSgpK3Uuc2xpY2UoMSkpO2xldCBrPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUygiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLCJzdmciKTtmb3IobGV0W0gsaGVdb2YgT2JqZWN0LmVudHJpZXMoe3ZpZXdCb3g6IjAgMCAyNCAyNCIsd2lkdGg6IjIwIixoZWlnaHQ6IjIwIixmaWxsOiJub25lIixzdHJva2U6ImN1cnJlbnRDb2xvciIsInN0cm9rZS13aWR0aCI6IjIiLCJzdHJva2UtbGluZWNhcCI6InJvdW5kIiwic3Ryb2tlLWxpbmVqb2luIjoicm91bmQiLCJhcmlhLWhpZGRlbiI6InRydWUiLGZvY3VzYWJsZToiZmFsc2UifSkpay5zZXRBdHRyaWJ1dGUoSCxoZSk7bGV0IEM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIsInBhdGgiKTtDLnNldEF0dHJpYnV0ZSgiZCIsYyksay5hcHBlbmQoQyksbS5hcHBlbmQoayksbS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsKCk9PngodSkse3NpZ25hbDpoLnNpZ25hbH0pLGQuYXBwZW5kKG0pfW8uYXBwZW5kKGQpLGEucGFuQ29udHJvbHM9ZH1mdW5jdGlvbiBNKCl7bGV0IGQ9YS5pbnN0YW5jZT8uZ2V0RWxlbWVudHMoKS5oYW5kbGUsdT1OdW1iZXIoZD8uZ2V0QXR0cmlidXRlKCJhcmlhLXZhbHVlbm93IikpO2QmJk51bWJlci5pc0Zpbml0ZSh1KSYmZC5zZXRBdHRyaWJ1dGUoImFyaWEtdmFsdWV0ZXh0Iix1dChpLHUpKX1mdW5jdGlvbiBJKCl7bGV0IGQ9YS5pbnN0YW5jZTtpZighZClyZXR1cm47bGV0IHU9ZC5nZXRFbGVtZW50cygpO2kuc2V0QXR0cmlidXRlKCJyb2xlIiwiZ3JvdXAiKSxpLnNldEF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIsbCgiY29tcGFyaXNvbkxhYmVsIikpLGkucmVtb3ZlQXR0cmlidXRlKCJhcmlhLWxhYmVsbGVkYnkiKSx1LmNvbnRhaW5lci5yZW1vdmVBdHRyaWJ1dGUoInJvbGUiKSx1LmNvbnRhaW5lci5yZW1vdmVBdHRyaWJ1dGUoImFyaWEtbGFiZWwiKSx1LmhhbmRsZS5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLGwoInNsaWRlckxhYmVsIikpO2ZvcihsZXQgbSBvZlt1LmJlZm9yZUltYWdlLHUuYWZ0ZXJJbWFnZV0pbS5yZW1vdmVBdHRyaWJ1dGUoInJvbGUiKTtmb3IobGV0W20sa11vZltbInpvb20taW4iLCJ6b29tSW5MYWJlbCJdLFsiem9vbS1vdXQiLCJ6b29tT3V0TGFiZWwiXSxbInpvb20tcmVzZXQiLCJyZXNldFpvb21MYWJlbCJdLFsiZnVsbHNjcmVlbi1idG4iLGQuaXNGdWxsc2NyZWVuKCk/ImV4aXRGdWxsc2NyZWVuTGFiZWwiOiJlbnRlckZ1bGxzY3JlZW5MYWJlbCJdXSlpLnF1ZXJ5U2VsZWN0b3IoIi5jaS1iZWZvcmUtYWZ0ZXItIittKT8uc2V0QXR0cmlidXRlKCJhcmlhLWxhYmVsIixsKGspKTtpLnF1ZXJ5U2VsZWN0b3IoIi5jaS1iZWZvcmUtYWZ0ZXItZnVsbHNjcmVlbi1idG4iKT8ucmVtb3ZlQXR0cmlidXRlKCJhcmlhLXByZXNzZWQiKTtsZXQgYz1pLnF1ZXJ5U2VsZWN0b3IoIi5jaS1iZWZvcmUtYWZ0ZXItc2Nyb2xsLWhpbnQiKTtjJiYoYy50ZXh0Q29udGVudD1sKCJzY3JvbGxIaW50VGV4dCIpKSxpLnF1ZXJ5U2VsZWN0b3JBbGwoInN2ZyIpLmZvckVhY2gobT0+e20uc2V0QXR0cmlidXRlKCJhcmlhLWhpZGRlbiIsInRydWUiKSxtLnNldEF0dHJpYnV0ZSgiZm9jdXNhYmxlIiwiZmFsc2UiKX0pfWZ1bmN0aW9uIFAoKXtpZihhLmluc3RhbmNlfHwhaS5pc0Nvbm5lY3RlZHx8bi5sZW5ndGghPT0yfHwhbi5ldmVyeSh1PT51LmNvbXBsZXRlJiZ1Lm5hdHVyYWxXaWR0aD4wKSlyZXR1cm47bGV0IGQ9bi5tYXAodT0+eGUodS5nZXRBdHRyaWJ1dGUoInNyYyIpLGRvY3VtZW50LmJhc2VVUkkpKTtpZighZC5zb21lKHU9PiF1KSl0cnl7by5oaWRkZW49ITEsYS5pbnN0YW5jZT1uZXcgcShvLHsuLi5zLGJlZm9yZVNyYzpkWzBdLGFmdGVyU3JjOmRbMV0sYmVmb3JlQWx0Om5bMF0uZ2V0QXR0cmlidXRlKCJhbHQiKT8/IiIsYWZ0ZXJBbHQ6blsxXS5nZXRBdHRyaWJ1dGUoImFsdCIpPz8iIixvbkZ1bGxzY3JlZW5DaGFuZ2UoKXtJKCksdygpfSxvblpvb206dyxvblNsaWRlOmd9KSxJKCksTSgpO2xldCB1PW5ldyBNdXRhdGlvbk9ic2VydmVyKE0pO3Uub2JzZXJ2ZShhLmluc3RhbmNlLmdldEVsZW1lbnRzKCkuaGFuZGxlLHthdHRyaWJ1dGVzOiEwLGF0dHJpYnV0ZUZpbHRlcjpbImFyaWEtdmFsdWVub3ciXX0pLGguc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IiwoKT0+dS5kaXNjb25uZWN0KCkpLHooKSxhLmxheW91dD1QZShpLGEuaW5zdGFuY2UpLGkucXVlcnlTZWxlY3RvckFsbCgiYnV0dG9uIikuZm9yRWFjaChjPT57Zm9yKGxldCBtIG9mWyJjbGljayIsImRibGNsaWNrIiwibW91c2Vkb3duIiwidG91Y2hzdGFydCJdKWMuYWRkRXZlbnRMaXN0ZW5lcihtLGs9Pmsuc3RvcFByb3BhZ2F0aW9uKCkse3NpZ25hbDpoLnNpZ25hbH0pfSksaS5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVyZG93biIsZyx7Y2FwdHVyZTohMCxzaWduYWw6aC5zaWduYWx9KSxpLmFkZEV2ZW50TGlzdGVuZXIoImtleWRvd24iLGM9PntsZXQgbT17QXJyb3dMZWZ0OiJsZWZ0IixBcnJvd1JpZ2h0OiJyaWdodCIsQXJyb3dVcDoidXAiLEFycm93RG93bjoiZG93biJ9O2MuYWx0S2V5JiYhYy5jdHJsS2V5JiYhYy5tZXRhS2V5JiZtW2Mua2V5XSYmYS5pbnN0YW5jZS5nZXRab29tKCk+MT8oYy5wcmV2ZW50RGVmYXVsdCgpLGMuc3RvcFByb3BhZ2F0aW9uKCkseChtW2Mua2V5XSkpOiFjLmFsdEtleSYmIWMuY3RybEtleSYmIWMubWV0YUtleSYmWy4uLk9iamVjdC5rZXlzKG0pLCJIb21lIiwiRW5kIiwiKyIsIj0iLCItIiwiMCJdLmluY2x1ZGVzKGMua2V5KSYmZygpfSx7Y2FwdHVyZTohMCxzaWduYWw6aC5zaWduYWx9KSx3KCksaS5zZXRBdHRyaWJ1dGUoImRhdGEtZWQtYmEtcmVhZHkiLCJ0cnVlIil9Y2F0Y2h7YS5sYXlvdXQ/LmRpc3Bvc2UoKSxhLmxheW91dD1udWxsLGEuaW5zdGFuY2U/LmRlc3Ryb3koKSxhLmluc3RhbmNlPW51bGwsby5yZXBsYWNlQ2hpbGRyZW4oKSxvLmhpZGRlbj0hMCxiKCl9fWZ1bmN0aW9uIEYoKXtoLmFib3J0KCksYS5sYXlvdXQ/LmRpc3Bvc2UoKSxhLmxheW91dD1udWxsLGEuaW5zdGFuY2U/LmRlc3Ryb3koKSxhLmluc3RhbmNlPW51bGwsYigpLG8uaGlkZGVuPSEwLGkucmVtb3ZlQXR0cmlidXRlKCJkYXRhLWVkLWJhLXJlYWR5IiksUy5kZWxldGUoaSl9bi5mb3JFYWNoKGQ9PmQuYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsUCx7c2lnbmFsOmguc2lnbmFsfSkpLFAoKX1mdW5jdGlvbiBjZSgpe2ZvcihsZXRbaSxlXW9mIFMpKCFpLmlzQ29ubmVjdGVkfHwhaS5tYXRjaGVzKEQpfHxLKGksImZhbGxiYWNrIikhPT1lLmZhbGxiYWNrfHxLKGksIm1vdW50IikhPT1lLm1vdW50fHxlLmltYWdlcy5zb21lKHQ9PiFlLmZhbGxiYWNrLmNvbnRhaW5zKHQpKSkmJmUuZGlzcG9zZSgpO2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoRCkuZm9yRWFjaChpPT57Uy5oYXMoaSl8fEFlKGkpfSl9ZnVuY3Rpb24gRWUoaSxlPSExKXtsZXQgdD1TLmdldChpKSxvPXQmJmkuY29udGFpbnMoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCksbj10Py5jZmcuYW5pbWF0ZSYmIXQudXNlck1vdmVkP3QuY2ZnLmluaXRpYWxQb3NpdGlvbjp0Py5pbnN0YW5jZT8uZ2V0UG9zaXRpb24oKTt0Py5kaXNwb3NlKCksQWUoaSxlKTtsZXQgcj1TLmdldChpKT8uaW5zdGFuY2U7ciYmZSYmbiE9PXZvaWQgMCYmci5zZXRQb3NpdGlvbihuKSxyJiZvJiZyLmdldEVsZW1lbnRzKCkuaGFuZGxlLmZvY3VzKHtwcmV2ZW50U2Nyb2xsOiEwfSl9dmFyIGJ0PW5ldyBNdXRhdGlvbk9ic2VydmVyKGk9PntsZXQgZT1uZXcgU2V0LHQ9ITE7Zm9yKGxldCBvIG9mIGkpe2xldCBuPWFlKG8udGFyZ2V0KT9vLnRhcmdldDpvLnRhcmdldC5wYXJlbnRFbGVtZW50O2lmKG4/LmNsb3Nlc3QoIi5lZC1iZWZvcmUtYWZ0ZXJfX21vdW50LCAuZWQtYmVmb3JlLWFmdGVyX19kb2NrIil8fG8udHlwZT09PSJjaGlsZExpc3QiJiZbLi4uby5hZGRlZE5vZGVzLC4uLm8ucmVtb3ZlZE5vZGVzXS5ldmVyeShzPT5hZShzKSYmcy5tYXRjaGVzKCIuZWQtYmVmb3JlLWFmdGVyX19kb2NrIikpKWNvbnRpbnVlO2xldCByPW4/LmNsb3Nlc3QoRCk7by50eXBlPT09ImF0dHJpYnV0ZXMiJiZyP2UuYWRkKHIpOm8udHlwZT09PSJjaGlsZExpc3QiJiYociYmZS5hZGQociksWy4uLm8uYWRkZWROb2RlcywuLi5vLnJlbW92ZWROb2Rlc10uc29tZShzPT5hZShzKSYmKHMubWF0Y2hlcyhEKXx8cy5xdWVyeVNlbGVjdG9yKEQpKSkmJih0PSEwKSl9Zm9yKGxldCBvIG9mIGUpby5pc0Nvbm5lY3RlZCYmRWUobyk7dCYmY2UoKX0pO2J0Lm9ic2VydmUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LHtjaGlsZExpc3Q6ITAsc3VidHJlZTohMCxhdHRyaWJ1dGVzOiEwLGF0dHJpYnV0ZUZpbHRlcjpbLi4uc2UubWFwKGk9PnJlKGkucGF0aCkpLCJzcmMiLCJhbHQiLCJsb2FkaW5nIiwiZGF0YS1ldGNoLWhhcy1jdXN0b20tY2xhc3NlcyJdfSk7TGUuYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIiwoKT0+e2ZvcihsZXQgaSBvZlsuLi5TLmtleXMoKV0pRWUoaSwhMCl9KTtnbG9iYWxUaGlzW2R0XT17c2NhbjpjZSxkZXN0cm95KGkpe1MuZ2V0KGkpPy5kaXNwb3NlKCl9LGdldChpKXtyZXR1cm4gUy5nZXQoaSk/Lmluc3RhbmNlfHxudWxsfX07Y2UoKTt9KSgpOwoKfQo=",
"id": "1v7ckj2"
},
"tag": "div",
"attributes": {
"data-ed-before-after": "",
"style": "--_ed-ba-ratio: {props.comparison.aspectRatio.equal('custom', props.comparison.customAspectRatio, props.comparison.aspectRatio)};",
"data-ed-ba-content-show-labels": "{props.content.showLabels}",
"data-ed-ba-content-before-label": "{props.content.beforeLabel}",
"data-ed-ba-content-after-label": "{props.content.afterLabel}",
"data-ed-ba-content-label-position": "{props.content.labelPosition}",
"data-ed-ba-comparison-orientation": "{props.comparison.orientation}",
"data-ed-ba-comparison-initial-position": "{props.comparison.initialPosition}",
"data-ed-ba-comparison-mode": "{props.comparison.mode}",
"data-ed-ba-comparison-handle-style": "{props.comparison.handleStyle}",
"data-ed-ba-comparison-aspect-ratio": "{props.comparison.aspectRatio}",
"data-ed-ba-comparison-custom-aspect-ratio": "{props.comparison.customAspectRatio}",
"data-ed-ba-comparison-object-fit": "{props.comparison.objectFit}",
"data-ed-ba-animation-enabled": "{props.animation.enabled}",
"data-ed-ba-animation-duration": "{props.animation.duration}",
"data-ed-ba-animation-delay": "{props.animation.delay}",
"data-ed-ba-animation-once": "{props.animation.once}",
"data-ed-ba-zoom-enabled": "{props.zoom.enabled}",
"data-ed-ba-zoom-maximum": "{props.zoom.maximum}",
"data-ed-ba-zoom-controls": "{props.zoom.controls}",
"data-ed-ba-zoom-controls-position": "{props.zoom.controlsPosition}",
"data-ed-ba-zoom-scroll-hint": "{props.zoom.scrollHint}",
"data-ed-ba-fullscreen": "{props.fullscreen}",
"data-ed-ba-performance-loading": "{props.performance.loading}",
"data-ed-ba-accessibility-comparison-label": "{props.accessibility.comparisonLabel}",
"data-ed-ba-accessibility-slider-label": "{props.accessibility.sliderLabel}",
"data-ed-ba-accessibility-zoom-in-label": "{props.accessibility.zoomInLabel}",
"data-ed-ba-accessibility-zoom-out-label": "{props.accessibility.zoomOutLabel}",
"data-ed-ba-accessibility-reset-zoom-label": "{props.accessibility.resetZoomLabel}",
"data-ed-ba-accessibility-pan-left-label": "{props.accessibility.panLeftLabel}",
"data-ed-ba-accessibility-pan-right-label": "{props.accessibility.panRightLabel}",
"data-ed-ba-accessibility-pan-up-label": "{props.accessibility.panUpLabel}",
"data-ed-ba-accessibility-pan-down-label": "{props.accessibility.panDownLabel}",
"data-ed-ba-accessibility-enter-fullscreen-label": "{props.accessibility.enterFullscreenLabel}",
"data-ed-ba-accessibility-exit-fullscreen-label": "{props.accessibility.exitFullscreenLabel}",
"data-ed-ba-accessibility-scroll-hint-text": "{props.accessibility.scrollHintText}",
"class": "ed-before-after"
},
"styles": [
"7vz25q6"
]
},
"innerBlocks": [
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Fallback"
},
"tag": "div",
"attributes": {
"class": "ed-before-after__fallback"
},
"styles": [
"r3ohlh2"
]
},
"innerBlocks": [
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Figure"
},
"tag": "figure",
"attributes": {
"class": "ed-before-after__figure"
},
"styles": [
"kl484w1"
]
},
"innerBlocks": [
{
"blockName": "etch/condition",
"attrs": {
"condition": {
"leftHand": "props.content.beforeImage",
"operator": "isTruthy",
"rightHand": null
},
"conditionString": "props.content.beforeImage"
},
"innerBlocks": [
{
"blockName": "etch/dynamic-image",
"attrs": {
"tag": "img",
"attributes": {
"mediaId": "{props.content.beforeImage}",
"alt": "{props.content.beforeAlt}",
"useSrcSet": "false",
"maximumSize": "{props.performance.imageSize}",
"loading": "{props.performance.loading}"
}
},
"innerBlocks": [],
"innerHTML": "\n\n",
"innerContent": [
"\n",
"\n"
]
}
],
"innerHTML": "\n\n",
"innerContent": [
"\n",
null,
"\n"
]
},
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Caption"
},
"tag": "figcaption",
"attributes": {
"class": "ed-before-after__caption"
},
"styles": [
"ktw39ju"
]
},
"innerBlocks": [
{
"blockName": "etch/text",
"attrs": {
"metadata": {
"name": "Text"
},
"content": "{props.content.beforeLabel}"
},
"innerBlocks": [],
"innerHTML": "",
"innerContent": []
}
],
"innerHTML": "\n\n",
"innerContent": [
"\n",
null,
"\n"
]
}
],
"innerHTML": "\n\n\n\n",
"innerContent": [
"\n",
null,
"\n\n",
null,
"\n"
]
},
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Figure"
},
"tag": "figure",
"attributes": {
"class": "ed-before-after__figure"
},
"styles": [
"kl484w1"
]
},
"innerBlocks": [
{
"blockName": "etch/condition",
"attrs": {
"condition": {
"leftHand": "props.content.afterImage",
"operator": "isTruthy",
"rightHand": null
},
"conditionString": "props.content.afterImage"
},
"innerBlocks": [
{
"blockName": "etch/dynamic-image",
"attrs": {
"tag": "img",
"attributes": {
"mediaId": "{props.content.afterImage}",
"alt": "{props.content.afterAlt}",
"useSrcSet": "false",
"maximumSize": "{props.performance.imageSize}",
"loading": "{props.performance.loading}"
}
},
"innerBlocks": [],
"innerHTML": "\n\n",
"innerContent": [
"\n",
"\n"
]
}
],
"innerHTML": "\n\n",
"innerContent": [
"\n",
null,
"\n"
]
},
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Caption"
},
"tag": "figcaption",
"attributes": {
"class": "ed-before-after__caption"
},
"styles": [
"ktw39ju"
]
},
"innerBlocks": [
{
"blockName": "etch/text",
"attrs": {
"metadata": {
"name": "Text"
},
"content": "{props.content.afterLabel}"
},
"innerBlocks": [],
"innerHTML": "",
"innerContent": []
}
],
"innerHTML": "\n\n",
"innerContent": [
"\n",
null,
"\n"
]
}
],
"innerHTML": "\n\n\n\n",
"innerContent": [
"\n",
null,
"\n\n",
null,
"\n"
]
}
],
"innerHTML": "\n\n\n\n",
"innerContent": [
"\n",
null,
"\n\n",
null,
"\n"
]
},
{
"blockName": "etch/element",
"attrs": {
"metadata": {
"name": "Mount"
},
"tag": "div",
"attributes": {
"hidden": "",
"class": "ed-before-after__mount"
},
"styles": [
"djm3wvy"
]
},
"innerBlocks": [],
"innerHTML": "\n\n",
"innerContent": [
"\n",
"\n"
]
}
],
"innerHTML": "\n\n\n\n",
"innerContent": [
"\n",
null,
"\n\n",
null,
"\n"
]
}
],
"properties": [
{
"name": "Content",
"key": "content",
"description": "Content settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Before image",
"key": "beforeImage",
"description": "Choose a WordPress image with the native Media selector; IDs are site-local.",
"type": {
"primitive": "string",
"specialized": "wpMediaId"
},
"default": ""
},
{
"name": "Before alt",
"key": "beforeAlt",
"description": "Describe the before image; empty explicitly means decorative.",
"type": {
"primitive": "string"
},
"default": ""
},
{
"name": "After image",
"key": "afterImage",
"description": "Choose a WordPress image with the native Media selector; IDs are site-local.",
"type": {
"primitive": "string",
"specialized": "wpMediaId"
},
"default": ""
},
{
"name": "After alt",
"key": "afterAlt",
"description": "Describe the after image; empty explicitly means decorative.",
"type": {
"primitive": "string"
},
"default": ""
},
{
"name": "Show labels",
"key": "showLabels",
"description": "Show both editable side labels.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "true",
"selectOptionsString": "On : true\nOff : false"
},
{
"name": "Before label",
"key": "beforeLabel",
"description": "Visible before label.",
"type": {
"primitive": "string"
},
"default": "Before"
},
{
"name": "After label",
"key": "afterLabel",
"description": "Visible after label.",
"type": {
"primitive": "string"
},
"default": "After"
},
{
"name": "Label position",
"key": "labelPosition",
"description": "Native label position; in vertical mode these place labels left/right.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "top",
"selectOptionsString": "Top : top\nBottom : bottom"
}
]
},
{
"name": "Comparison",
"key": "comparison",
"description": "Comparison settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Orientation",
"key": "orientation",
"description": "Divider movement axis.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "horizontal",
"selectOptionsString": "Horizontal : horizontal\nVertical : vertical"
},
{
"name": "Initial position (%)",
"key": "initialPosition",
"description": "Clamp to 0–100; invalid values use 50.",
"type": {
"primitive": "string"
},
"default": "50"
},
{
"name": "Interaction mode",
"key": "mode",
"description": "Drag recommended; hover targets fine-pointer devices. Keyboard always works.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "drag",
"selectOptionsString": "Drag : drag\nClick : click\nHover : hover"
},
{
"name": "Handle style",
"key": "handleStyle",
"description": "Native handle appearance.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "arrows",
"selectOptionsString": "Arrows : arrows\nCircle : circle\nLine : line"
},
{
"name": "Viewport ratio",
"key": "aspectRatio",
"description": "Choose a preset or Custom to use Custom viewport ratio.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "4 / 3",
"selectOptionsString": "4 / 3 : 4 / 3\n16 / 9 : 16 / 9\n1 / 1 : 1 / 1\n3 / 4 : 3 / 4\nCustom : custom"
},
{
"name": "Custom viewport ratio",
"key": "customAspectRatio",
"description": "Used when Viewport ratio is Custom. Enter width / height, e.g. 21 / 9, or a decimal, e.g. 1.85. Positive numbers only; invalid values use 4 / 3.",
"type": {
"primitive": "string"
},
"default": "4 / 3"
},
{
"name": "Image fit",
"key": "objectFit",
"description": "Both images share the same fitting strategy.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "cover",
"selectOptionsString": "Cover (crop to fill) : cover\nContain (show whole image) : contain"
}
]
},
{
"name": "Entrance animation",
"key": "animation",
"description": "Entrance animation settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Entrance animation",
"key": "enabled",
"description": "Optional native ease-out entrance; disabled for reduced motion.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "false",
"selectOptionsString": "Off : false\nOn : true"
},
{
"name": "Duration (ms)",
"key": "duration",
"description": "0–10000 milliseconds.",
"type": {
"primitive": "string"
},
"default": "800"
},
{
"name": "Delay (ms)",
"key": "delay",
"description": "0–10000 milliseconds.",
"type": {
"primitive": "string"
},
"default": "0"
},
{
"name": "Animate once",
"key": "once",
"description": "Use the native animateOnce option.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "true",
"selectOptionsString": "On : true\nOff : false"
}
]
},
{
"name": "Zoom and pan",
"key": "zoom",
"description": "Zoom and pan settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Enable zoom",
"key": "enabled",
"description": "Native zoom/pan, keyboard shortcuts and pinch gestures.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "false",
"selectOptionsString": "Off : false\nOn : true"
},
{
"name": "Maximum zoom",
"key": "maximum",
"description": "Clamp to 1–10; invalid values use 4.",
"type": {
"primitive": "string"
},
"default": "4"
},
{
"name": "Show zoom controls",
"key": "controls",
"description": "Show native buttons when zoom is enabled.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "true",
"selectOptionsString": "On : true\nOff : false"
},
{
"name": "Zoom controls position",
"key": "controlsPosition",
"description": "Native control position.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "bottom-right",
"selectOptionsString": "Bottom right : bottom-right\nBottom center : bottom-center\nBottom left : bottom-left\nTop right : top-right\nTop center : top-center\nTop left : top-left"
},
{
"name": "Show scroll hint",
"key": "scrollHint",
"description": "Show the localized native scroll hint when zoom is enabled.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "true",
"selectOptionsString": "On : true\nOff : false"
}
]
},
{
"name": "Enable fullscreen button",
"key": "fullscreen",
"description": "Native browser fullscreen where supported; frontend only.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "false",
"selectOptionsString": "Off : false\nOn : true"
},
{
"name": "Performance",
"key": "performance",
"description": "Performance settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Image loading",
"key": "loading",
"description": "Native Dynamic Image loading owns laziness; vendor lazyLoad is disabled.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "lazy",
"selectOptionsString": "Lazy : lazy\nEager (above the fold) : eager"
},
{
"name": "Image size",
"key": "imageSize",
"description": "WordPress size loaded for both images. Pick the smallest that stays sharp at the displayed width; sizes follow Settings → Media, and an image smaller than the size loads its original.",
"type": {
"primitive": "string",
"specialized": "select"
},
"default": "full",
"selectOptionsString": "Full (original upload) : full\n2048 px : 2048x2048\n1536 px : 1536x1536\nLarge (1024 px) : large\nMedium large (768 px) : medium_large\nMedium (300 px) : medium"
}
]
},
{
"name": "Accessible names and translations",
"key": "accessibility",
"description": "Accessible names and translations settings.",
"type": {
"primitive": "object",
"specialized": "group"
},
"properties": [
{
"name": "Comparison name",
"key": "comparisonLabel",
"description": "Accessible name of the native comparison group.",
"type": {
"primitive": "string"
},
"default": "Before and after image comparison"
},
{
"name": "Slider name and instructions",
"key": "sliderLabel",
"description": "Accessible name of the divider slider. Screen readers say how to adjust a slider; added instructions must not mention keys only.",
"type": {
"primitive": "string"
},
"default": "Image comparison divider"
},
{
"name": "Zoom in",
"key": "zoomInLabel",
"description": "Zoom-in button name.",
"type": {
"primitive": "string"
},
"default": "Zoom in"
},
{
"name": "Zoom out",
"key": "zoomOutLabel",
"description": "Zoom-out button name.",
"type": {
"primitive": "string"
},
"default": "Zoom out"
},
{
"name": "Reset zoom",
"key": "resetZoomLabel",
"description": "Reset button name.",
"type": {
"primitive": "string"
},
"default": "Reset zoom"
},
{
"name": "Move image left",
"key": "panLeftLabel",
"description": "Name of the left pan button; Alt+Left also moves the zoomed image.",
"type": {
"primitive": "string"
},
"default": "Move image left"
},
{
"name": "Move image right",
"key": "panRightLabel",
"description": "Name of the right pan button; Alt+Right also moves the zoomed image.",
"type": {
"primitive": "string"
},
"default": "Move image right"
},
{
"name": "Move image up",
"key": "panUpLabel",
"description": "Name of the up pan button; Alt+Up also moves the zoomed image.",
"type": {
"primitive": "string"
},
"default": "Move image up"
},
{
"name": "Move image down",
"key": "panDownLabel",
"description": "Name of the down pan button; Alt+Down also moves the zoomed image.",
"type": {
"primitive": "string"
},
"default": "Move image down"
},
{
"name": "Enter fullscreen",
"key": "enterFullscreenLabel",
"description": "Fullscreen entry name.",
"type": {
"primitive": "string"
},
"default": "Enter fullscreen"
},
{
"name": "Exit fullscreen",
"key": "exitFullscreenLabel",
"description": "Fullscreen exit name.",
"type": {
"primitive": "string"
},
"default": "Exit fullscreen"
},
{
"name": "Scroll hint",
"key": "scrollHintText",
"description": "Visible zoom hint text.",
"type": {
"primitive": "string"
},
"default": "Ctrl / ⌘ + scroll or pinch to zoom"
}
]
}
],
"description": "ED Before / After Image 1.0.0-beta.3 — accessible local image comparison"
}
},
"version": 2.1
}
Stay up to date. Etch won’t update a pasted component for you. Subscribe and get one email when a new version is out.
10 comparisons in real layouts
Drag, click or hover over the photos, or press Tab and use the arrow keys. Switch to Mobile to see the layouts at phone width.
What it does
One pasted component and no setup. The comparison engine is bundled, so there is no plugin, no CDN, no Cloudimage account and no extra request.
Real images in the HTML
Etch renders both photos with their alt text on the server. Without JavaScript, or when a photo fails to load, the comparison falls back to the two images side by side.
Drag, click or hover
Drag the divider, click to move it there, or let it follow the mouse. The keyboard always works: arrow keys, Shift for steps of 10%, Home and End.
Accessible by default
A named slider that screen readers announce as a percentage, visible focus, 44 px targets and alt text for each photo. Reduced motion skips the entrance animation.
Any frame ratio
4 / 3, 16 / 9, square, portrait or your own, such as 21 / 9. Cover crops both photos to fill the frame, Contain shows them whole, and a variable sets the crop focus.
Zoom, pan and fullscreen
Zoom up to 10× with buttons, keys, Ctrl / ⌘ + scroll or a pinch, move around the zoomed photo, and open the comparison in fullscreen.
Every word translatable
Edit the labels, the zoom hint and every accessible name in the props panel. The slider value follows the page language, such as “50 %” in German.
40 styling variables
Handle, divider, labels, buttons, crop focus and the focus ring, set on any parent class. ACSS 4 tokens with plain fallbacks, so it works without Automatic.css too.
Live in the builder
The canvas runs the real comparison, so every prop edit shows at once, without saving. Drag the divider or zoom right in the canvas to try a setting.
Add it in four steps
No plugin and no build step. The component brings its own CSS and script with the comparison engine bundled, so nothing loads from a CDN. It works with or without Automatic.css 4.
Shows without its styles? It was pasted but not saved, and pasting again won’t repair it. Delete ED Before / After Image from your components, paste it again and click Save.
- Copy the componentUse Copy component at the top of this page, or download the .json file.
- Paste it on the Etch canvasSelect where it should go, press Ctrl+V or ⌘V, then click Save. Etch adds the component to your list right away but stores its CSS only when you save.
- Choose two photosIn Content, pick Before image and After image from the Media Library and describe each one in Before alt and After alt. Photos taken from the same spot, at the same size, line up best.
- Save and open the pageThe canvas runs the real comparison as soon as both photos are chosen, so every setting you change shows at once. On the page, visitors drag, click or use the keyboard.
39 settings in the Etch props panel
Grouped as in the Etch props panel, where each setting has help text too. Only the two photos are required; until you choose them, a new comparison shows an empty frame with its labels.
Free to use. Not for resale.
Licensed under FSL-1.1-MIT, the Functional Source License with an MIT future license. Each version becomes MIT-licensed two years after its release.
- Use it on unlimited personal, client and commercial websites
- Modify and adapt it however you like
- Use it in paid design and development work for your clients
- Sell it, or a modified version, as a component: in a library, bundle, template kit, plugin or marketplace listing
- Offer it in another commercial product or service that competes with it
Keep the copyright and license notices in the code, and link to this page instead of re-hosting the download, so everyone gets fixes and updates. Read the full license
Third-party code
This component bundles the open-source library below. It keeps its own license, and FSL-1.1-MIT does not apply to it. Its notice is included in the component’s script and CSS; keep it when you use or change the component.
- @cloudimage/before-after1.0.4
How to update
Etch has no update button for pasted components. Pasting a newer version over an installed one changes nothing: Etch keeps the component and the CSS it already has. To update, reinstall in five steps.
- Note what you setWrite down the settings of each comparison, including its photos and alt text, and copy any CSS you changed in the component’s own styles.
- Delete the componentIn Etch, delete ED Before / After Image from your components. Every comparison disappears from every page that used it.
- Delete its stylesIn the Style Manager, search for ed-before-after and delete the five styles listed below.
- Paste the new versionCopy or download the new JSON from this page, paste it on the canvas and click Save. Etch creates the component and its CSS fresh.
- Put your comparisons backInsert a comparison wherever one was, choose its photos, re-enter its settings and save. Reload any other open builder tab.
Styles to delete in step 3
.ed-before-after.ed-before-after__fallback.ed-before-after__figure.ed-before-after__caption.ed-before-after__mount
Trade-offs
- Placements are not kept. Etch doesn’t link old comparisons to the new component, so you insert each one again and re-enter its settings.
- Edits inside the component’s CSS are replaced. Keep overrides on a parent class with the
--ed-before-after-*variables; those survive an update. - Skipping a step leaves a mix. Without step 2, Etch keeps the old component. Without step 3, the new version runs on the old CSS.
Coming from 1.0.0-beta.2? Follow the five steps above. Settings, classes and styling variables are unchanged, so you can re-enter your settings as they were. Subscribe and you’ll get one email when the next version is out.
What changed
Versions follow semantic versioning. When an update changes how existing options behave, its entry says so.
1.0.0-beta.3Latest
- FixedOn phones and tablets, a two-finger pinch that starts on a comparison with zoom off now zooms the page, like anywhere else, and leaves the divider where it is. Before, the comparison blocked page zoom and the first finger moved the divider. With zoom on, a pinch still zooms the photo.
- FixedThe fullscreen button no longer reports a pressed state next to its changing name. TalkBack read it as “checked. Exit fullscreen. Switch”; now it’s “Enter fullscreen” or “Exit fullscreen”, read as a button.
- ChangedThe default slider name is now “Image comparison divider”. The old default, “Image comparison. Use arrow keys to move the divider.”, told phone users to use keys they don’t have; screen readers already say how to adjust a slider. A name you entered yourself is kept.
- ChangedThe script and the CSS of
.ed-before-afterchanged, so update the component and its styles together (see How to update). Props, Select values, classes and the 40 styling variables are the same. - TestedTalkBack on Android, Safari on iPhone and iPad in the iOS Simulator, and Chrome, Firefox, Microsoft Edge and WebKit on the desktop. With TalkBack, swiping up or down doesn’t move the divider, because Chrome doesn’t pass that gesture to the slider: focus the slider, then double-tap and hold and drag. It stays a beta until it’s checked on a real phone and the Shift and Alt + arrow keys are tried in Safari.
1.0.0-beta.2
- ReleasedFirst public version. It stays a beta until NVDA, VoiceOver on iOS, TalkBack, Microsoft Edge and touch devices are tested.
Tell me what this component needs
A bug, a missing option, or anything that made the component awkward to use in a real build — it all belongs here. The versions above are the ones it was tested on; if yours differ, say so.