Files
rspade_system/storage-working/rsx-tmp/babel_5b4c9961a869fa2be956d30e52fcee9c.js
root 9ebcc359ae Fix code quality violations and enhance ROUTE-EXISTS-01 rule
Implement JQHTML function cache ID system and fix bundle compilation
Implement underscore prefix for system tables
Fix JS syntax linter to support decorators and grant exception to Task system
SPA: Update planning docs and wishlists with remaining features
SPA: Document Navigation API abandonment and future enhancements
Implement SPA browser integration with History API (Phase 1)
Convert contacts view page to SPA action
Convert clients pages to SPA actions and document conversion procedure
SPA: Merge GET parameters and update documentation
Implement SPA route URL generation in JavaScript and PHP
Implement SPA bootstrap controller architecture
Add SPA routing manual page (rsx:man spa)
Add SPA routing documentation to CLAUDE.md
Phase 4 Complete: Client-side SPA routing implementation
Update get_routes() consumers for unified route structure
Complete SPA Phase 3: PHP-side route type detection and is_spa flag
Restore unified routes structure and Manifest_Query class
Refactor route indexing and add SPA infrastructure
Phase 3 Complete: SPA route registration in manifest
Implement SPA Phase 2: Extract router code and test decorators
Rename Jqhtml_Component to Component and complete SPA foundation setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 17:48:15 +00:00

406 lines
52 KiB
JavaScript
Executable File

"use strict";
/**
* DataGrid Component (Phase 1)
*
* Due to the more dynamic nature of this component, we are handling load / render lifecycles
* directly in this class rather than using the on_load lifecycle event
*
* **Features**:
* - Ajax data fetching
* - Sorting (click headers)
* - Pagination (next/prev/page select)
* - Row selection (checkboxes)
* - CSV export (selected rows, current page)
* - URL state synchronization
*
* **Usage**:
* ```html
* <Contacts_DataGrid $api="Frontend_Contacts_Controller" />
* ```
*
* **Required Args**:
* - `api` - Controller class name with datagrid_fetch() Ajax endpoint
*
* **Optional Args**:
* - `per_page` - Default rows per page (default: 25)
* - `sort` - Default sort column (default: first column)
* - `order` - Default sort order (default: 'asc')
*/
class DataGrid_Abstract extends Component {
// Initialize data before first render
on_create() {
let that = this;
// Initialize data state immediately so template can render
that.data.rows = [];
that.data.loading = true;
that.data.is_empty = false;
that.data.loaded = false;
that.data.total_pages = 0;
}
// Calls when datagrid first initialized
async on_ready() {
var _that$args$per_page, _that$args$sort, _that$args$order;
let that = this;
if (!that.args.data_source) {
console.error('Datagrid ' + that.component_name() + ' requires args.data_source set to a Ajax_Endpoint object');
return;
}
// Store defaults for later comparison
that.data.default_page = 1;
that.data.default_per_page = (_that$args$per_page = that.args.per_page) !== null && _that$args$per_page !== void 0 ? _that$args$per_page : 15;
that.data.default_sort = (_that$args$sort = that.args.sort) !== null && _that$args$sort !== void 0 ? _that$args$sort : null;
that.data.default_order = (_that$args$order = that.args.order) !== null && _that$args$order !== void 0 ? _that$args$order : 'asc';
that.data.default_filter = '';
// Set configured values
that.data.per_page = that.data.default_per_page;
// Initialize state from URL hash if present, otherwise use defaults
const hash_page = Rsx.get_page_state(that._cid + '_page');
const hash_sort = Rsx.get_page_state(that._cid + '_sort');
const hash_order = Rsx.get_page_state(that._cid + '_order');
const hash_filter = Rsx.get_page_state(that._cid + '_filter');
that.data.page = hash_page ? int(hash_page) : that.data.default_page;
that.data.sort = hash_sort || that.data.default_sort;
that.data.order = hash_order || that.data.default_order;
that.data.filter = hash_filter || that.data.default_filter;
that.register_render_callbacks();
that.register_filter_handlers();
// If hash had a filter value, populate the filter input
if (that.data.filter) {
const $filter = that.$id('filter_input');
if ($filter && $filter.length > 0) {
$filter.val(that.data.filter);
}
}
// Measure row height and set fixed tbody height (all in one frame)
await that.measure_and_set_fixed_height();
// Fetch the initial page (respects hash state)
that.load_page(that.data.page);
}
// Update header only if sort/order changed
update_header() {
let that = this;
// Track last rendered state
if (!that._last_header_state) {
that._last_header_state = {};
}
const current = {
sort: that.data.sort,
order: that.data.order
};
// Only render if values changed
if (that._last_header_state.sort !== current.sort || that._last_header_state.order !== current.order) {
that._last_header_state = current;
that.id('datagrid_table_header').render();
}
}
// Update pagination only if values changed
update_pagination() {
let that = this;
// Track last rendered state
if (!that._last_pagination_state) {
that._last_pagination_state = {};
}
const current = {
page: that.data.page,
per_page: that.data.per_page,
total: that.data.total,
total_pages: that.data.total_pages
};
// Only render if values changed
if (that._last_pagination_state.page !== current.page || that._last_pagination_state.per_page !== current.per_page || that._last_pagination_state.total !== current.total || that._last_pagination_state.total_pages !== current.total_pages) {
that._last_pagination_state = current;
that.id('pagination_info').render();
that.id('pagination_controls').render();
}
}
// Load data for specified page and re-render data
async load_page(page) {
let that = this;
// Set loading state
that.data.loading = true;
that.data.page = page;
// Update UI with requested values (optimistic update)
that.update_header();
that.update_pagination();
// Only render loading state if no data yet (initial load)
if (that.data.rows.length === 0) {
that.id('datagrid_table_body').render();
}
const response = await Ajax.call(that.args.data_source, {
page: page,
per_page: that.data.per_page,
sort: that.data.sort,
order: that.data.order,
filter: that.data.filter
});
// Update data
that.data.loading = false;
that.data.loaded = true;
that.data.rows = response.records;
that.data.page = response.page;
that.data.per_page = response.per_page;
that.data.total = response.total;
that.data.total_pages = response.total_pages;
that.data.sort = response.sort;
that.data.order = response.order;
that.data.is_empty = response.records.length === 0;
// Persist state to URL hash for bookmarking/sharing
// Only set values that differ from defaults (null removes the key)
const state = {};
state[that._cid + '_page'] = that.data.page !== that.data.default_page ? that.data.page : null;
state[that._cid + '_sort'] = that.data.sort !== that.data.default_sort ? that.data.sort : null;
state[that._cid + '_order'] = that.data.order !== that.data.default_order ? that.data.order : null;
state[that._cid + '_filter'] = that.data.filter !== that.data.default_filter ? that.data.filter : null;
Rsx.set_all_page_state(state);
// Update UI with server response (only renders if changed)
that.id('datagrid_table_body').render();
that.update_header();
that.update_pagination();
// Scroll to top of datagrid if it's not currently visible
that.scroll_to_top_if_needed();
}
// The callbacks in this function fire after each targeted component re-renders
register_render_callbacks() {
let that = this;
// Attach row click handler - re-runs every time datagrid_table_body renders
that.id('datagrid_table_body').on('render', function () {
console.log('DGTB_R');
// Step 1: Wrap cells in data-href rows with anchor tags
$(this).find('tr[data-href]').each(function () {
let $row = $(this);
let href = $row.attr('data-href');
$row.find('td').each(function () {
// let $col = $(this);
// // Skip if cell already contains interactive elements
// if ($col.find('a, button, input, select, textarea').length > 0) {
// return;
// }
// // Wrap entire cell contents in an anchor (preserve DOM nodes for component lifecycle)
// let $anchor = $('<a>', {
// href: href,
// class: 'datagrid-row-link'
// });
// // Move existing child nodes into anchor (preserves components and their state)
// $col.contents().appendTo($anchor);
// // Add anchor to cell
// $col.append($anchor);
});
});
// Step 2: Find all cells with single anchor as only child and apply full-width styling
$(this).find('td').each(function () {
let $col = $(this);
let $children = $col.children();
// Check if cell contains exactly one direct child that is an anchor
if ($children.length === 1 && $children.first().is('a')) {
// Add class to transfer padding from cell to anchor
$col.addClass('has-full-link');
}
// Check if cell contains only text (no child elements)
else if ($children.length === 0) {
// Add class to apply vertical padding to text-only cells
$col.addClass('has-only-text');
}
});
});
// Attach sortable header click handler - re-runs every time datagrid_table_header renders
that.id('datagrid_table_header').on('render', function () {
// Transform th[data-sortby] elements by wrapping contents in clickable link
$(this).find('th[data-sortby]').each(function () {
let $th = $(this);
let sortby = $th.attr('data-sortby');
// TODO: Find out why this on('render') callback is being called twice/on already-processed HTML
// This unwrap logic shouldn't be necessary - template should render fresh each time
// For now, unwrap already-wrapped content to prevent double-wrapping
let $existing_link = $th.find('a.sortable-header');
let contents;
if ($existing_link.length > 0) {
// Unwrap - get the text content without the wrapper and arrows
contents = $existing_link.clone().find('i.bi').remove().end().html();
} else {
contents = $th.html();
}
// Build the arrow icon HTML if this column is currently sorted
let arrow = '';
if (that.data.sort === sortby) {
arrow = that.data.order === 'desc' ? '<i class="bi bi-chevron-up ms-1"></i>' : '<i class="bi bi-chevron-down ms-1"></i>';
}
// Replace contents with wrapped link (fresh wrapper every time)
$th.html(`<a href="#" class="sortable-header" data-sortby="${sortby}">${contents}${arrow}</a>`);
});
// Attach click handlers to the sortable links we just created
$(this).find('a.sortable-header[data-sortby]').on('click', function (e) {
e.preventDefault();
const sortby = $(this).attr('data-sortby');
that.sort_by(sortby);
});
});
// Attach pagination click handler - re-runs every time pagination_controls renders
that.id('pagination_controls').on('render', function () {
$(this).find('.page-link').on('click', function (e) {
e.preventDefault();
const $link = $(this);
const page = int($link.attr('data-page'));
// Ignore disabled/ellipsis clicks
if (!page || isNaN(page) || $link.parent().hasClass('disabled')) {
return;
}
// Load the requested page
that.load_page(page);
});
});
// Attach clear filter button handler - re-runs every time datagrid_table_body renders
that.id('datagrid_table_body').on('render', function () {
const $clear_btn = that.$id('clear_filter_btn');
if ($clear_btn && $clear_btn.length > 0) {
$clear_btn.on('click', function (e) {
e.preventDefault();
that.clear_filter();
});
}
});
}
// Sort by specified column, toggling order if already sorted by that column
sort_by(column) {
let that = this;
// Toggle order if clicking same column, otherwise default to asc
if (that.data.sort === column) {
that.data.order = that.data.order === 'asc' ? 'desc' : 'asc';
} else {
that.data.sort = column;
that.data.order = 'asc';
}
// Reload current page with new sort
that.id('datagrid_table_header').render();
that.load_page(that.data.page);
}
// Register filter input handlers
register_filter_handlers() {
let that = this;
// Find filter input by common identifiers
let $filter = that.$id('filter_input');
if (!$filter || $filter.length === 0) {
$filter = that.$.find('input[type="search"], input[type="text"].filter-input');
}
if ($filter && $filter.length > 0) {
$filter.on('input keyup', function () {
const filter_value = $(this).val();
that.filter_changed(filter_value);
});
}
}
filter_changed(filter) {
let that = this;
that.data.filter = filter;
that.load_page(1);
}
// Scroll to datagrid top if the top edge is not currently visible in viewport
scroll_to_top_if_needed() {
let that = this;
const $datagrid = that.$;
const datagridTop = $datagrid.offset().top;
const scrollTop = $(window).scrollTop();
// If datagrid top is above the current viewport, scroll to show it
if (datagridTop < scrollTop) {
// If datagrid is within 300px of page top, scroll to 0
if (datagridTop <= 300) {
window.scrollTo({
top: 0,
behavior: 'instant'
});
} else {
// Scroll to 20px above datagrid
window.scrollTo({
top: datagridTop - 20,
behavior: 'instant'
});
}
}
}
// Measure actual row height and set fixed tbody min-height
// All happens in one animation frame so user doesn't see it
async measure_and_set_fixed_height() {
let that = this;
// Wait for next animation frame to ensure DOM is ready
await sleep(0);
const $tbody = that.id('datagrid_table_body').$;
// Temporarily render a single measurement row
const $measurement_row = $('<tr>').css('visibility', 'hidden').html('<td>Measuring...</td>');
$tbody.append($measurement_row);
// Measure the row height
const row_height = $measurement_row.outerHeight();
// Remove measurement row
$measurement_row.remove();
// Calculate and set min-height based on per_page
const min_height = row_height * that.data.per_page;
$tbody.css('min-height', min_height + 'px');
// Store for future reference
that.data.row_height = row_height;
that.data.tbody_min_height = min_height;
}
// Clear filter and reset to page 1
clear_filter() {
let that = this;
that.data.filter = '';
// Clear the filter input
const $filter = that.$id('filter_input');
if ($filter && $filter.length > 0) {
$filter.val('');
}
// Reload from page 1
that.load_page(1);
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJEYXRhR3JpZF9BYnN0cmFjdCIsIkpxaHRtbF9Db21wb25lbnQiLCJvbl9jcmVhdGUiLCJ0aGF0IiwiZGF0YSIsInJvd3MiLCJsb2FkaW5nIiwiaXNfZW1wdHkiLCJsb2FkZWQiLCJ0b3RhbF9wYWdlcyIsIm9uX3JlYWR5IiwiX3RoYXQkYXJncyRwZXJfcGFnZSIsIl90aGF0JGFyZ3Mkc29ydCIsIl90aGF0JGFyZ3Mkb3JkZXIiLCJhcmdzIiwiZGF0YV9zb3VyY2UiLCJjb25zb2xlIiwiZXJyb3IiLCJjb21wb25lbnRfbmFtZSIsImRlZmF1bHRfcGFnZSIsImRlZmF1bHRfcGVyX3BhZ2UiLCJwZXJfcGFnZSIsImRlZmF1bHRfc29ydCIsInNvcnQiLCJkZWZhdWx0X29yZGVyIiwib3JkZXIiLCJkZWZhdWx0X2ZpbHRlciIsImhhc2hfcGFnZSIsIlJzeCIsImdldF9wYWdlX3N0YXRlIiwiX2NpZCIsImhhc2hfc29ydCIsImhhc2hfb3JkZXIiLCJoYXNoX2ZpbHRlciIsInBhZ2UiLCJpbnQiLCJmaWx0ZXIiLCJyZWdpc3Rlcl9yZW5kZXJfY2FsbGJhY2tzIiwicmVnaXN0ZXJfZmlsdGVyX2hhbmRsZXJzIiwiJGZpbHRlciIsIiRpZCIsImxlbmd0aCIsInZhbCIsIm1lYXN1cmVfYW5kX3NldF9maXhlZF9oZWlnaHQiLCJsb2FkX3BhZ2UiLCJ1cGRhdGVfaGVhZGVyIiwiX2xhc3RfaGVhZGVyX3N0YXRlIiwiY3VycmVudCIsImlkIiwicmVuZGVyIiwidXBkYXRlX3BhZ2luYXRpb24iLCJfbGFzdF9wYWdpbmF0aW9uX3N0YXRlIiwidG90YWwiLCJyZXNwb25zZSIsIkFqYXgiLCJjYWxsIiwicmVjb3JkcyIsInN0YXRlIiwic2V0X2FsbF9wYWdlX3N0YXRlIiwic2Nyb2xsX3RvX3RvcF9pZl9uZWVkZWQiLCJvbiIsImxvZyIsIiQiLCJmaW5kIiwiZWFjaCIsIiRyb3ciLCJocmVmIiwiYXR0ciIsIiRjb2wiLCIkY2hpbGRyZW4iLCJjaGlsZHJlbiIsImZpcnN0IiwiaXMiLCJhZGRDbGFzcyIsIiR0aCIsInNvcnRieSIsIiRleGlzdGluZ19saW5rIiwiY29udGVudHMiLCJjbG9uZSIsInJlbW92ZSIsImVuZCIsImh0bWwiLCJhcnJvdyIsImUiLCJwcmV2ZW50RGVmYXVsdCIsInNvcnRfYnkiLCIkbGluayIsImlzTmFOIiwicGFyZW50IiwiaGFzQ2xhc3MiLCIkY2xlYXJfYnRuIiwiY2xlYXJfZmlsdGVyIiwiY29sdW1uIiwiZmlsdGVyX3ZhbHVlIiwiZmlsdGVyX2NoYW5nZWQiLCIkZGF0YWdyaWQiLCJkYXRhZ3JpZFRvcCIsIm9mZnNldCIsInRvcCIsInNjcm9sbFRvcCIsIndpbmRvdyIsInNjcm9sbFRvIiwiYmVoYXZpb3IiLCJzbGVlcCIsIiR0Ym9keSIsIiRtZWFzdXJlbWVudF9yb3ciLCJjc3MiLCJhcHBlbmQiLCJyb3dfaGVpZ2h0Iiwib3V0ZXJIZWlnaHQiLCJtaW5faGVpZ2h0IiwidGJvZHlfbWluX2hlaWdodCJdLCJzb3VyY2VzIjpbInJzeC90aGVtZS9jb21wb25lbnRzL2RhdGFncmlkL2RhdGFncmlkX2Fic3RyYWN0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGF0YUdyaWQgQ29tcG9uZW50IChQaGFzZSAxKVxuICpcbiAqIER1ZSB0byB0aGUgbW9yZSBkeW5hbWljIG5hdHVyZSBvZiB0aGlzIGNvbXBvbmVudCwgd2UgYXJlIGhhbmRsaW5nIGxvYWQgLyByZW5kZXIgbGlmZWN5Y2xlc1xuICogZGlyZWN0bHkgaW4gdGhpcyBjbGFzcyByYXRoZXIgdGhhbiB1c2luZyB0aGUgb25fbG9hZCBsaWZlY3ljbGUgZXZlbnRcbiAqXG4gKiAqKkZlYXR1cmVzKio6XG4gKiAtIEFqYXggZGF0YSBmZXRjaGluZ1xuICogLSBTb3J0aW5nIChjbGljayBoZWFkZXJzKVxuICogLSBQYWdpbmF0aW9uIChuZXh0L3ByZXYvcGFnZSBzZWxlY3QpXG4gKiAtIFJvdyBzZWxlY3Rpb24gKGNoZWNrYm94ZXMpXG4gKiAtIENTViBleHBvcnQgKHNlbGVjdGVkIHJvd3MsIGN1cnJlbnQgcGFnZSlcbiAqIC0gVVJMIHN0YXRlIHN5bmNocm9uaXphdGlvblxuICpcbiAqICoqVXNhZ2UqKjpcbiAqIGBgYGh0bWxcbiAqIDxDb250YWN0c19EYXRhR3JpZCAkYXBpPVwiRnJvbnRlbmRfQ29udGFjdHNfQ29udHJvbGxlclwiIC8+XG4gKiBgYGBcbiAqXG4gKiAqKlJlcXVpcmVkIEFyZ3MqKjpcbiAqIC0gYGFwaWAgLSBDb250cm9sbGVyIGNsYXNzIG5hbWUgd2l0aCBkYXRhZ3JpZF9mZXRjaCgpIEFqYXggZW5kcG9pbnRcbiAqXG4gKiAqKk9wdGlvbmFsIEFyZ3MqKjpcbiAqIC0gYHBlcl9wYWdlYCAtIERlZmF1bHQgcm93cyBwZXIgcGFnZSAoZGVmYXVsdDogMjUpXG4gKiAtIGBzb3J0YCAtIERlZmF1bHQgc29ydCBjb2x1bW4gKGRlZmF1bHQ6IGZpcnN0IGNvbHVtbilcbiAqIC0gYG9yZGVyYCAtIERlZmF1bHQgc29ydCBvcmRlciAoZGVmYXVsdDogJ2FzYycpXG4gKi9cbmNsYXNzIERhdGFHcmlkX0Fic3RyYWN0IGV4dGVuZHMgSnFodG1sX0NvbXBvbmVudCB7XG4gICAgLy8gSW5pdGlhbGl6ZSBkYXRhIGJlZm9yZSBmaXJzdCByZW5kZXJcbiAgICBvbl9jcmVhdGUoKSB7XG4gICAgICAgIGxldCB0aGF0ID0gdGhpcztcblxuICAgICAgICAvLyBJbml0aWFsaXplIGRhdGEgc3RhdGUgaW1tZWRpYXRlbHkgc28gdGVtcGxhdGUgY2FuIHJlbmRlclxuICAgICAgICB0aGF0LmRhdGEucm93cyA9IFtdO1xuICAgICAgICB0aGF0LmRhdGEubG9hZGluZyA9IHRydWU7XG4gICAgICAgIHRoYXQuZGF0YS5pc19lbXB0eSA9IGZhbHNlO1xuICAgICAgICB0aGF0LmRhdGEubG9hZGVkID0gZmFsc2U7XG4gICAgICAgIHRoYXQuZGF0YS50b3RhbF9wYWdlcyA9IDA7XG4gICAgfVxuXG4gICAgLy8gQ2FsbHMgd2hlbiBkYXRhZ3JpZCBmaXJzdCBpbml0aWFsaXplZFxuICAgIGFzeW5jIG9uX3JlYWR5KCkge1xuICAgICAgICBsZXQgdGhhdCA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCF0aGF0LmFyZ3MuZGF0YV9zb3VyY2UpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0RhdGFncmlkICcgKyB0aGF0LmNvbXBvbmVudF9uYW1lKCkgKyAnIHJlcXVpcmVzIGFyZ3MuZGF0YV9zb3VyY2Ugc2V0IHRvIGEgQWpheF9FbmRwb2ludCBvYmplY3QnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0b3JlIGRlZmF1bHRzIGZvciBsYXRlciBjb21wYXJpc29uXG4gICAgICAgIHRoYXQuZGF0YS5kZWZhdWx0X3BhZ2UgPSAxO1xuICAgICAgICB0aGF0LmRhdGEuZGVmYXVsdF9wZXJfcGFnZSA9IHRoYXQuYXJncy5wZXJfcGFnZSA/PyAxNTtcbiAgICAgICAgdGhhdC5kYXRhLmRlZmF1bHRfc29ydCA9IHRoYXQuYXJncy5zb3J0ID8/IG51bGw7XG4gICAgICAgIHRoYXQuZGF0YS5kZWZhdWx0X29yZGVyID0gdGhhdC5hcmdzLm9yZGVyID8/ICdhc2MnO1xuICAgICAgICB0aGF0LmRhdGEuZGVmYXVsdF9maWx0ZXIgPSAnJztcblxuICAgICAgICAvLyBTZXQgY29uZmlndXJlZCB2YWx1ZXNcbiAgICAgICAgdGhhdC5kYXRhLnBlcl9wYWdlID0gdGhhdC5kYXRhLmRlZmF1bHRfcGVyX3BhZ2U7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBzdGF0ZSBmcm9tIFVSTCBoYXNoIGlmIHByZXNlbnQsIG90aGVyd2lzZSB1c2UgZGVmYXVsdHNcbiAgICAgICAgY29uc3QgaGFzaF9wYWdlID0gUnN4LmdldF9wYWdlX3N0YXRlKHRoYXQuX2NpZCArICdfcGFnZScpO1xuICAgICAgICBjb25zdCBoYXNoX3NvcnQgPSBSc3guZ2V0X3BhZ2Vfc3RhdGUodGhhdC5fY2lkICsgJ19zb3J0Jyk7XG4gICAgICAgIGNvbnN0IGhhc2hfb3JkZXIgPSBSc3guZ2V0X3BhZ2Vfc3RhdGUodGhhdC5fY2lkICsgJ19vcmRlcicpO1xuICAgICAgICBjb25zdCBoYXNoX2ZpbHRlciA9IFJzeC5nZXRfcGFnZV9zdGF0ZSh0aGF0Ll9jaWQgKyAnX2ZpbHRlcicpO1xuXG4gICAgICAgIHRoYXQuZGF0YS5wYWdlID0gaGFzaF9wYWdlID8gaW50KGhhc2hfcGFnZSkgOiB0aGF0LmRhdGEuZGVmYXVsdF9wYWdlO1xuICAgICAgICB0aGF0LmRhdGEuc29ydCA9IGhhc2hfc29ydCB8fCB0aGF0LmRhdGEuZGVmYXVsdF9zb3J0O1xuICAgICAgICB0aGF0LmRhdGEub3JkZXIgPSBoYXNoX29yZGVyIHx8IHRoYXQuZGF0YS5kZWZhdWx0X29yZGVyO1xuICAgICAgICB0aGF0LmRhdGEuZmlsdGVyID0gaGFzaF9maWx0ZXIgfHwgdGhhdC5kYXRhLmRlZmF1bHRfZmlsdGVyO1xuXG4gICAgICAgIHRoYXQucmVnaXN0ZXJfcmVuZGVyX2NhbGxiYWNrcygpO1xuICAgICAgICB0aGF0LnJlZ2lzdGVyX2ZpbHRlcl9oYW5kbGVycygpO1xuXG4gICAgICAgIC8vIElmIGhhc2ggaGFkIGEgZmlsdGVyIHZhbHVlLCBwb3B1bGF0ZSB0aGUgZmlsdGVyIGlucHV0XG4gICAgICAgIGlmICh0aGF0LmRhdGEuZmlsdGVyKSB7XG4gICAgICAgICAgICBjb25zdCAkZmlsdGVyID0gdGhhdC4kaWQoJ2ZpbHRlcl9pbnB1dCcpO1xuICAgICAgICAgICAgaWYgKCRmaWx0ZXIgJiYgJGZpbHRlci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgJGZpbHRlci52YWwodGhhdC5kYXRhLmZpbHRlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNZWFzdXJlIHJvdyBoZWlnaHQgYW5kIHNldCBmaXhlZCB0Ym9keSBoZWlnaHQgKGFsbCBpbiBvbmUgZnJhbWUpXG4gICAgICAgIGF3YWl0IHRoYXQubWVhc3VyZV9hbmRfc2V0X2ZpeGVkX2hlaWdodCgpO1xuXG4gICAgICAgIC8vIEZldGNoIHRoZSBpbml0aWFsIHBhZ2UgKHJlc3BlY3RzIGhhc2ggc3RhdGUpXG4gICAgICAgIHRoYXQubG9hZF9wYWdlKHRoYXQuZGF0YS5wYWdlKTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgaGVhZGVyIG9ubHkgaWYgc29ydC9vcmRlciBjaGFuZ2VkXG4gICAgdXBkYXRlX2hlYWRlcigpIHtcbiAgICAgICAgbGV0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIC8vIFRyYWNrIGxhc3QgcmVuZGVyZWQgc3RhdGVcbiAgICAgICAgaWYgKCF0aGF0Ll9sYXN0X2hlYWRlcl9zdGF0ZSkge1xuICAgICAgICAgICAgdGhhdC5fbGFzdF9oZWFkZXJfc3RhdGUgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSB7XG4gICAgICAgICAgICBzb3J0OiB0aGF0LmRhdGEuc29ydCxcbiAgICAgICAgICAgIG9yZGVyOiB0aGF0LmRhdGEub3JkZXIsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gT25seSByZW5kZXIgaWYgdmFsdWVzIGNoYW5nZWRcbiAgICAgICAgaWYgKHRoYXQuX2xhc3RfaGVhZGVyX3N0YXRlLnNvcnQgIT09IGN1cnJlbnQuc29ydCB8fCB0aGF0Ll9sYXN0X2hlYWRlcl9zdGF0ZS5vcmRlciAhPT0gY3VycmVudC5vcmRlcikge1xuICAgICAgICAgICAgdGhhdC5fbGFzdF9oZWFkZXJfc3RhdGUgPSBjdXJyZW50O1xuICAgICAgICAgICAgdGhhdC5pZCgnZGF0YWdyaWRfdGFibGVfaGVhZGVyJykucmVuZGVyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgcGFnaW5hdGlvbiBvbmx5IGlmIHZhbHVlcyBjaGFuZ2VkXG4gICAgdXBkYXRlX3BhZ2luYXRpb24oKSB7XG4gICAgICAgIGxldCB0aGF0ID0gdGhpcztcblxuICAgICAgICAvLyBUcmFjayBsYXN0IHJlbmRlcmVkIHN0YXRlXG4gICAgICAgIGlmICghdGhhdC5fbGFzdF9wYWdpbmF0aW9uX3N0YXRlKSB7XG4gICAgICAgICAgICB0aGF0Ll9sYXN0X3BhZ2luYXRpb25fc3RhdGUgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSB7XG4gICAgICAgICAgICBwYWdlOiB0aGF0LmRhdGEucGFnZSxcbiAgICAgICAgICAgIHBlcl9wYWdlOiB0aGF0LmRhdGEucGVyX3BhZ2UsXG4gICAgICAgICAgICB0b3RhbDogdGhhdC5kYXRhLnRvdGFsLFxuICAgICAgICAgICAgdG90YWxfcGFnZXM6IHRoYXQuZGF0YS50b3RhbF9wYWdlcyxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBPbmx5IHJlbmRlciBpZiB2YWx1ZXMgY2hhbmdlZFxuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGF0Ll9sYXN0X3BhZ2luYXRpb25fc3RhdGUucGFnZSAhPT0gY3VycmVudC5wYWdlIHx8XG4gICAgICAgICAgICB0aGF0Ll9sYXN0X3BhZ2luYXRpb25fc3RhdGUucGVyX3BhZ2UgIT09IGN1cnJlbnQucGVyX3BhZ2UgfHxcbiAgICAgICAgICAgIHRoYXQuX2xhc3RfcGFnaW5hdGlvbl9zdGF0ZS50b3RhbCAhPT0gY3VycmVudC50b3RhbCB8fFxuICAgICAgICAgICAgdGhhdC5fbGFzdF9wYWdpbmF0aW9uX3N0YXRlLnRvdGFsX3BhZ2VzICE9PSBjdXJyZW50LnRvdGFsX3BhZ2VzXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhhdC5fbGFzdF9wYWdpbmF0aW9uX3N0YXRlID0gY3VycmVudDtcbiAgICAgICAgICAgIHRoYXQuaWQoJ3BhZ2luYXRpb25faW5mbycpLnJlbmRlcigpO1xuICAgICAgICAgICAgdGhhdC5pZCgncGFnaW5hdGlvbl9jb250cm9scycpLnJlbmRlcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTG9hZCBkYXRhIGZvciBzcGVjaWZpZWQgcGFnZSBhbmQgcmUtcmVuZGVyIGRhdGFcbiAgICBhc3luYyBsb2FkX3BhZ2UocGFnZSkge1xuICAgICAgICBsZXQgdGhhdCA9IHRoaXM7XG5cbiAgICAgICAgLy8gU2V0IGxvYWRpbmcgc3RhdGVcbiAgICAgICAgdGhhdC5kYXRhLmxvYWRpbmcgPSB0cnVlO1xuICAgICAgICB0aGF0LmRhdGEucGFnZSA9IHBhZ2U7XG5cbiAgICAgICAgLy8gVXBkYXRlIFVJIHdpdGggcmVxdWVzdGVkIHZhbHVlcyAob3B0aW1pc3RpYyB1cGRhdGUpXG4gICAgICAgIHRoYXQudXBkYXRlX2hlYWRlcigpO1xuICAgICAgICB0aGF0LnVwZGF0ZV9wYWdpbmF0aW9uKCk7XG5cbiAgICAgICAgLy8gT25seSByZW5kZXIgbG9hZGluZyBzdGF0ZSBpZiBubyBkYXRhIHlldCAoaW5pdGlhbCBsb2FkKVxuICAgICAgICBpZiAodGhhdC5kYXRhLnJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aGF0LmlkKCdkYXRhZ3JpZF90YWJsZV9ib2R5JykucmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IEFqYXguY2FsbCh0aGF0LmFyZ3MuZGF0YV9zb3VyY2UsIHtcbiAgICAgICAgICAgIHBhZ2U6IHBhZ2UsXG4gICAgICAgICAgICBwZXJfcGFnZTogdGhhdC5kYXRhLnBlcl9wYWdlLFxuICAgICAgICAgICAgc29ydDogdGhhdC5kYXRhLnNvcnQsXG4gICAgICAgICAgICBvcmRlcjogdGhhdC5kYXRhLm9yZGVyLFxuICAgICAgICAgICAgZmlsdGVyOiB0aGF0LmRhdGEuZmlsdGVyLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBVcGRhdGUgZGF0YVxuICAgICAgICB0aGF0LmRhdGEubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGF0LmRhdGEubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgdGhhdC5kYXRhLnJvd3MgPSByZXNwb25zZS5yZWNvcmRzO1xuICAgICAgICB0aGF0LmRhdGEucGFnZSA9IHJlc3BvbnNlLnBhZ2U7XG4gICAgICAgIHRoYXQuZGF0YS5wZXJfcGFnZSA9IHJlc3BvbnNlLnBlcl9wYWdlO1xuICAgICAgICB0aGF0LmRhdGEudG90YWwgPSByZXNwb25zZS50b3RhbDtcbiAgICAgICAgdGhhdC5kYXRhLnRvdGFsX3BhZ2VzID0gcmVzcG9uc2UudG90YWxfcGFnZXM7XG4gICAgICAgIHRoYXQuZGF0YS5zb3J0ID0gcmVzcG9uc2Uuc29ydDtcbiAgICAgICAgdGhhdC5kYXRhLm9yZGVyID0gcmVzcG9uc2Uub3JkZXI7XG4gICAgICAgIHRoYXQuZGF0YS5pc19lbXB0eSA9IHJlc3BvbnNlLnJlY29yZHMubGVuZ3RoID09PSAwO1xuXG4gICAgICAgIC8vIFBlcnNpc3Qgc3RhdGUgdG8gVVJMIGhhc2ggZm9yIGJvb2ttYXJraW5nL3NoYXJpbmdcbiAgICAgICAgLy8gT25seSBzZXQgdmFsdWVzIHRoYXQgZGlmZmVyIGZyb20gZGVmYXVsdHMgKG51bGwgcmVtb3ZlcyB0aGUga2V5KVxuICAgICAgICBjb25zdCBzdGF0ZSA9IHt9O1xuICAgICAgICBzdGF0ZVt0aGF0Ll9jaWQgKyAnX3BhZ2UnXSA9IHRoYXQuZGF0YS5wYWdlICE9PSB0aGF0LmRhdGEuZGVmYXVsdF9wYWdlID8gdGhhdC5kYXRhLnBhZ2UgOiBudWxsO1xuICAgICAgICBzdGF0ZVt0aGF0Ll9jaWQgKyAnX3NvcnQnXSA9IHRoYXQuZGF0YS5zb3J0ICE9PSB0aGF0LmRhdGEuZGVmYXVsdF9zb3J0ID8gdGhhdC5kYXRhLnNvcnQgOiBudWxsO1xuICAgICAgICBzdGF0ZVt0aGF0Ll9jaWQgKyAnX29yZGVyJ10gPSB0aGF0LmRhdGEub3JkZXIgIT09IHRoYXQuZGF0YS5kZWZhdWx0X29yZGVyID8gdGhhdC5kYXRhLm9yZGVyIDogbnVsbDtcbiAgICAgICAgc3RhdGVbdGhhdC5fY2lkICsgJ19maWx0ZXInXSA9IHRoYXQuZGF0YS5maWx0ZXIgIT09IHRoYXQuZGF0YS5kZWZhdWx0X2ZpbHRlciA/IHRoYXQuZGF0YS5maWx0ZXIgOiBudWxsO1xuXG4gICAgICAgIFJzeC5zZXRfYWxsX3BhZ2Vfc3RhdGUoc3RhdGUpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBVSSB3aXRoIHNlcnZlciByZXNwb25zZSAob25seSByZW5kZXJzIGlmIGNoYW5nZWQpXG4gICAgICAgIHRoYXQuaWQoJ2RhdGFncmlkX3RhYmxlX2JvZHknKS5yZW5kZXIoKTtcbiAgICAgICAgdGhhdC51cGRhdGVfaGVhZGVyKCk7XG4gICAgICAgIHRoYXQudXBkYXRlX3BhZ2luYXRpb24oKTtcblxuICAgICAgICAvLyBTY3JvbGwgdG8gdG9wIG9mIGRhdGFncmlkIGlmIGl0J3Mgbm90IGN1cnJlbnRseSB2aXNpYmxlXG4gICAgICAgIHRoYXQuc2Nyb2xsX3RvX3RvcF9pZl9uZWVkZWQoKTtcbiAgICB9XG5cbiAgICAvLyBUaGUgY2FsbGJhY2tzIGluIHRoaXMgZnVuY3Rpb24gZmlyZSBhZnRlciBlYWNoIHRhcmdldGVkIGNvbXBvbmVudCByZS1yZW5kZXJzXG4gICAgcmVnaXN0ZXJfcmVuZGVyX2NhbGxiYWNrcygpIHtcbiAgICAgICAgbGV0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIC8vIEF0dGFjaCByb3cgY2xpY2sgaGFuZGxlciAtIHJlLXJ1bnMgZXZlcnkgdGltZSBkYXRhZ3JpZF90YWJsZV9ib2R5IHJlbmRlcnNcbiAgICAgICAgdGhhdC5pZCgnZGF0YWdyaWRfdGFibGVfYm9keScpLm9uKCdyZW5kZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnREdUQl9SJyk7XG4gICAgICAgICAgICAvLyBTdGVwIDE6IFdyYXAgY2VsbHMgaW4gZGF0YS1ocmVmIHJvd3Mgd2l0aCBhbmNob3IgdGFnc1xuICAgICAgICAgICAgJCh0aGlzKVxuICAgICAgICAgICAgICAgIC5maW5kKCd0cltkYXRhLWhyZWZdJylcbiAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCAkcm93ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGhyZWYgPSAkcm93LmF0dHIoJ2RhdGEtaHJlZicpO1xuXG4gICAgICAgICAgICAgICAgICAgICRyb3cuZmluZCgndGQnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxldCAkY29sID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIFNraXAgaWYgY2VsbCBhbHJlYWR5IGNvbnRhaW5zIGludGVyYWN0aXZlIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiAoJGNvbC5maW5kKCdhLCBidXR0b24sIGlucHV0LCBzZWxlY3QsIHRleHRhcmVhJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIFdyYXAgZW50aXJlIGNlbGwgY29udGVudHMgaW4gYW4gYW5jaG9yIChwcmVzZXJ2ZSBET00gbm9kZXMgZm9yIGNvbXBvbmVudCBsaWZlY3ljbGUpXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQgJGFuY2hvciA9ICQoJzxhPicsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICBocmVmOiBocmVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIGNsYXNzOiAnZGF0YWdyaWQtcm93LWxpbmsnXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIE1vdmUgZXhpc3RpbmcgY2hpbGQgbm9kZXMgaW50byBhbmNob3IgKHByZXNlcnZlcyBjb21wb25lbnRzIGFuZCB0aGVpciBzdGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICRjb2wuY29udGVudHMoKS5hcHBlbmRUbygkYW5jaG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIC8vIEFkZCBhbmNob3IgdG8gY2VsbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gJGNvbC5hcHBlbmQoJGFuY2hvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBTdGVwIDI6IEZpbmQgYWxsIGNlbGxzIHdpdGggc2luZ2xlIGFuY2hvciBhcyBvbmx5IGNoaWxkIGFuZCBhcHBseSBmdWxsLXdpZHRoIHN0eWxpbmdcbiAgICAgICAgICAgICQodGhpcylcbiAgICAgICAgICAgICAgICAuZmluZCgndGQnKVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0ICRjb2wgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgJGNoaWxkcmVuID0gJGNvbC5jaGlsZHJlbigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGNlbGwgY29udGFpbnMgZXhhY3RseSBvbmUgZGlyZWN0IGNoaWxkIHRoYXQgaXMgYW4gYW5jaG9yXG4gICAgICAgICAgICAgICAgICAgIGlmICgkY2hpbGRyZW4ubGVuZ3RoID09PSAxICYmICRjaGlsZHJlbi5maXJzdCgpLmlzKCdhJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBjbGFzcyB0byB0cmFuc2ZlciBwYWRkaW5nIGZyb20gY2VsbCB0byBhbmNob3JcbiAgICAgICAgICAgICAgICAgICAgICAgICRjb2wuYWRkQ2xhc3MoJ2hhcy1mdWxsLWxpbmsnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBjZWxsIGNvbnRhaW5zIG9ubHkgdGV4dCAobm8gY2hpbGQgZWxlbWVudHMpXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCRjaGlsZHJlbi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBjbGFzcyB0byBhcHBseSB2ZXJ0aWNhbCBwYWRkaW5nIHRvIHRleHQtb25seSBjZWxsc1xuICAgICAgICAgICAgICAgICAgICAgICAgJGNvbC5hZGRDbGFzcygnaGFzLW9ubHktdGV4dCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEF0dGFjaCBzb3J0YWJsZSBoZWFkZXIgY2xpY2sgaGFuZGxlciAtIHJlLXJ1bnMgZXZlcnkgdGltZSBkYXRhZ3JpZF90YWJsZV9oZWFkZXIgcmVuZGVyc1xuICAgICAgICB0aGF0LmlkKCdkYXRhZ3JpZF90YWJsZV9oZWFkZXInKS5vbigncmVuZGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gVHJhbnNmb3JtIHRoW2RhdGEtc29ydGJ5XSBlbGVtZW50cyBieSB3cmFwcGluZyBjb250ZW50cyBpbiBjbGlja2FibGUgbGlua1xuICAgICAgICAgICAgJCh0aGlzKVxuICAgICAgICAgICAgICAgIC5maW5kKCd0aFtkYXRhLXNvcnRieV0nKVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0ICR0aCA9ICQodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBzb3J0YnkgPSAkdGguYXR0cignZGF0YS1zb3J0YnknKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBGaW5kIG91dCB3aHkgdGhpcyBvbigncmVuZGVyJykgY2FsbGJhY2sgaXMgYmVpbmcgY2FsbGVkIHR3aWNlL29uIGFscmVhZHktcHJvY2Vzc2VkIEhUTUxcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyB1bndyYXAgbG9naWMgc2hvdWxkbid0IGJlIG5lY2Vzc2FyeSAtIHRlbXBsYXRlIHNob3VsZCByZW5kZXIgZnJlc2ggZWFjaCB0aW1lXG4gICAgICAgICAgICAgICAgICAgIC8vIEZvciBub3csIHVud3JhcCBhbHJlYWR5LXdyYXBwZWQgY29udGVudCB0byBwcmV2ZW50IGRvdWJsZS13cmFwcGluZ1xuICAgICAgICAgICAgICAgICAgICBsZXQgJGV4aXN0aW5nX2xpbmsgPSAkdGguZmluZCgnYS5zb3J0YWJsZS1oZWFkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRlbnRzO1xuICAgICAgICAgICAgICAgICAgICBpZiAoJGV4aXN0aW5nX2xpbmsubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVW53cmFwIC0gZ2V0IHRoZSB0ZXh0IGNvbnRlbnQgd2l0aG91dCB0aGUgd3JhcHBlciBhbmQgYXJyb3dzXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50cyA9ICRleGlzdGluZ19saW5rLmNsb25lKCkuZmluZCgnaS5iaScpLnJlbW92ZSgpLmVuZCgpLmh0bWwoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRzID0gJHRoLmh0bWwoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEJ1aWxkIHRoZSBhcnJvdyBpY29uIEhUTUwgaWYgdGhpcyBjb2x1bW4gaXMgY3VycmVudGx5IHNvcnRlZFxuICAgICAgICAgICAgICAgICAgICBsZXQgYXJyb3cgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuZGF0YS5zb3J0ID09PSBzb3J0YnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycm93ID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0LmRhdGEub3JkZXIgPT09ICdkZXNjJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/ICc8aSBjbGFzcz1cImJpIGJpLWNoZXZyb24tdXAgbXMtMVwiPjwvaT4nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJzxpIGNsYXNzPVwiYmkgYmktY2hldnJvbi1kb3duIG1zLTFcIj48L2k+JztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlcGxhY2UgY29udGVudHMgd2l0aCB3cmFwcGVkIGxpbmsgKGZyZXNoIHdyYXBwZXIgZXZlcnkgdGltZSlcbiAgICAgICAgICAgICAgICAgICAgJHRoLmh0bWwoYDxhIGhyZWY9XCIjXCIgY2xhc3M9XCJzb3J0YWJsZS1oZWFkZXJcIiBkYXRhLXNvcnRieT1cIiR7c29ydGJ5fVwiPiR7Y29udGVudHN9JHthcnJvd308L2E+YCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBjbGljayBoYW5kbGVycyB0byB0aGUgc29ydGFibGUgbGlua3Mgd2UganVzdCBjcmVhdGVkXG4gICAgICAgICAgICAkKHRoaXMpXG4gICAgICAgICAgICAgICAgLmZpbmQoJ2Euc29ydGFibGUtaGVhZGVyW2RhdGEtc29ydGJ5XScpXG4gICAgICAgICAgICAgICAgLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc29ydGJ5ID0gJCh0aGlzKS5hdHRyKCdkYXRhLXNvcnRieScpO1xuICAgICAgICAgICAgICAgICAgICB0aGF0LnNvcnRfYnkoc29ydGJ5KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQXR0YWNoIHBhZ2luYXRpb24gY2xpY2sgaGFuZGxlciAtIHJlLXJ1bnMgZXZlcnkgdGltZSBwYWdpbmF0aW9uX2NvbnRyb2xzIHJlbmRlcnNcbiAgICAgICAgdGhhdC5pZCgncGFnaW5hdGlvbl9jb250cm9scycpLm9uKCdyZW5kZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkKHRoaXMpXG4gICAgICAgICAgICAgICAgLmZpbmQoJy5wYWdlLWxpbmsnKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgJGxpbmsgPSAkKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gaW50KCRsaW5rLmF0dHIoJ2RhdGEtcGFnZScpKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZ25vcmUgZGlzYWJsZWQvZWxsaXBzaXMgY2xpY2tzXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFnZSB8fCBpc05hTihwYWdlKSB8fCAkbGluay5wYXJlbnQoKS5oYXNDbGFzcygnZGlzYWJsZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTG9hZCB0aGUgcmVxdWVzdGVkIHBhZ2VcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5sb2FkX3BhZ2UocGFnZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEF0dGFjaCBjbGVhciBmaWx0ZXIgYnV0dG9uIGhhbmRsZXIgLSByZS1ydW5zIGV2ZXJ5IHRpbWUgZGF0YWdyaWRfdGFibGVfYm9keSByZW5kZXJzXG4gICAgICAgIHRoYXQuaWQoJ2RhdGFncmlkX3RhYmxlX2JvZHknKS5vbigncmVuZGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgJGNsZWFyX2J0biA9IHRoYXQuJGlkKCdjbGVhcl9maWx0ZXJfYnRuJyk7XG4gICAgICAgICAgICBpZiAoJGNsZWFyX2J0biAmJiAkY2xlYXJfYnRuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAkY2xlYXJfYnRuLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5jbGVhcl9maWx0ZXIoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gU29ydCBieSBzcGVjaWZpZWQgY29sdW1uLCB0b2dnbGluZyBvcmRlciBpZiBhbHJlYWR5IHNvcnRlZCBieSB0aGF0IGNvbHVtblxuICAgIHNvcnRfYnkoY29sdW1uKSB7XG4gICAgICAgIGxldCB0aGF0ID0gdGhpcztcblxuICAgICAgICAvLyBUb2dnbGUgb3JkZXIgaWYgY2xpY2tpbmcgc2FtZSBjb2x1bW4sIG90aGVyd2lzZSBkZWZhdWx0IHRvIGFzY1xuICAgICAgICBpZiAodGhhdC5kYXRhLnNvcnQgPT09IGNvbHVtbikge1xuICAgICAgICAgICAgdGhhdC5kYXRhLm9yZGVyID0gdGhhdC5kYXRhLm9yZGVyID09PSAnYXNjJyA/ICdkZXNjJyA6ICdhc2MnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhhdC5kYXRhLnNvcnQgPSBjb2x1bW47XG4gICAgICAgICAgICB0aGF0LmRhdGEub3JkZXIgPSAnYXNjJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbG9hZCBjdXJyZW50IHBhZ2Ugd2l0aCBuZXcgc29ydFxuICAgICAgICB0aGF0LmlkKCdkYXRhZ3JpZF90YWJsZV9oZWFkZXInKS5yZW5kZXIoKTtcbiAgICAgICAgdGhhdC5sb2FkX3BhZ2UodGhhdC5kYXRhLnBhZ2UpO1xuICAgIH1cblxuICAgIC8vIFJlZ2lzdGVyIGZpbHRlciBpbnB1dCBoYW5kbGVyc1xuICAgIHJlZ2lzdGVyX2ZpbHRlcl9oYW5kbGVycygpIHtcbiAgICAgICAgbGV0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIC8vIEZpbmQgZmlsdGVyIGlucHV0IGJ5IGNvbW1vbiBpZGVudGlmaWVyc1xuICAgICAgICBsZXQgJGZpbHRlciA9IHRoYXQuJGlkKCdmaWx0ZXJfaW5wdXQnKTtcbiAgICAgICAgaWYgKCEkZmlsdGVyIHx8ICRmaWx0ZXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAkZmlsdGVyID0gdGhhdC4kLmZpbmQoJ2lucHV0W3R5cGU9XCJzZWFyY2hcIl0sIGlucHV0W3R5cGU9XCJ0ZXh0XCJdLmZpbHRlci1pbnB1dCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCRmaWx0ZXIgJiYgJGZpbHRlci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAkZmlsdGVyLm9uKCdpbnB1dCBrZXl1cCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXJfdmFsdWUgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgICAgICAgICAgIHRoYXQuZmlsdGVyX2NoYW5nZWQoZmlsdGVyX3ZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZmlsdGVyX2NoYW5nZWQoZmlsdGVyKSB7XG4gICAgICAgIGxldCB0aGF0ID0gdGhpcztcblxuICAgICAgICB0aGF0LmRhdGEuZmlsdGVyID0gZmlsdGVyO1xuICAgICAgICB0aGF0LmxvYWRfcGFnZSgxKTtcbiAgICB9XG5cbiAgICAvLyBTY3JvbGwgdG8gZGF0YWdyaWQgdG9wIGlmIHRoZSB0b3AgZWRnZSBpcyBub3QgY3VycmVudGx5IHZpc2libGUgaW4gdmlld3BvcnRcbiAgICBzY3JvbGxfdG9fdG9wX2lmX25lZWRlZCgpIHtcbiAgICAgICAgbGV0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0ICRkYXRhZ3JpZCA9IHRoYXQuJDtcbiAgICAgICAgY29uc3QgZGF0YWdyaWRUb3AgPSAkZGF0YWdyaWQub2Zmc2V0KCkudG9wO1xuICAgICAgICBjb25zdCBzY3JvbGxUb3AgPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCk7XG5cbiAgICAgICAgLy8gSWYgZGF0YWdyaWQgdG9wIGlzIGFib3ZlIHRoZSBjdXJyZW50IHZpZXdwb3J0LCBzY3JvbGwgdG8gc2hvdyBpdFxuICAgICAgICBpZiAoZGF0YWdyaWRUb3AgPCBzY3JvbGxUb3ApIHtcbiAgICAgICAgICAgIC8vIElmIGRhdGFncmlkIGlzIHdpdGhpbiAzMDBweCBvZiBwYWdlIHRvcCwgc2Nyb2xsIHRvIDBcbiAgICAgICAgICAgIGlmIChkYXRhZ3JpZFRvcCA8PSAzMDApIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuc2Nyb2xsVG8oeyB0b3A6IDAsIGJlaGF2aW9yOiAnaW5zdGFudCcgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFNjcm9sbCB0byAyMHB4IGFib3ZlIGRhdGFncmlkXG4gICAgICAgICAgICAgICAgd2luZG93LnNjcm9sbFRvKHsgdG9wOiBkYXRhZ3JpZFRvcCAtIDIwLCBiZWhhdmlvcjogJ2luc3RhbnQnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTWVhc3VyZSBhY3R1YWwgcm93IGhlaWdodCBhbmQgc2V0IGZpeGVkIHRib2R5IG1pbi1oZWlnaHRcbiAgICAvLyBBbGwgaGFwcGVucyBpbiBvbmUgYW5pbWF0aW9uIGZyYW1lIHNvIHVzZXIgZG9lc24ndCBzZWUgaXRcbiAgICBhc3luYyBtZWFzdXJlX2FuZF9zZXRfZml4ZWRfaGVpZ2h0KCkge1xuICAgICAgICBsZXQgdGhhdCA9IHRoaXM7XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgbmV4dCBhbmltYXRpb24gZnJhbWUgdG8gZW5zdXJlIERPTSBpcyByZWFkeVxuICAgICAgICBhd2FpdCBzbGVlcCgwKTtcblxuICAgICAgICBjb25zdCAkdGJvZHkgPSB0aGF0LmlkKCdkYXRhZ3JpZF90YWJsZV9ib2R5JykuJDtcblxuICAgICAgICAvLyBUZW1wb3JhcmlseSByZW5kZXIgYSBzaW5nbGUgbWVhc3VyZW1lbnQgcm93XG4gICAgICAgIGNvbnN0ICRtZWFzdXJlbWVudF9yb3cgPSAkKCc8dHI+JykuY3NzKCd2aXNpYmlsaXR5JywgJ2hpZGRlbicpLmh0bWwoJzx0ZD5NZWFzdXJpbmcuLi48L3RkPicpO1xuICAgICAgICAkdGJvZHkuYXBwZW5kKCRtZWFzdXJlbWVudF9yb3cpO1xuXG4gICAgICAgIC8vIE1lYXN1cmUgdGhlIHJvdyBoZWlnaHRcbiAgICAgICAgY29uc3Qgcm93X2hlaWdodCA9ICRtZWFzdXJlbWVudF9yb3cub3V0ZXJIZWlnaHQoKTtcblxuICAgICAgICAvLyBSZW1vdmUgbWVhc3VyZW1lbnQgcm93XG4gICAgICAgICRtZWFzdXJlbWVudF9yb3cucmVtb3ZlKCk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIGFuZCBzZXQgbWluLWhlaWdodCBiYXNlZCBvbiBwZXJfcGFnZVxuICAgICAgICBjb25zdCBtaW5faGVpZ2h0ID0gcm93X2hlaWdodCAqIHRoYXQuZGF0YS5wZXJfcGFnZTtcbiAgICAgICAgJHRib2R5LmNzcygnbWluLWhlaWdodCcsIG1pbl9oZWlnaHQgKyAncHgnKTtcblxuICAgICAgICAvLyBTdG9yZSBmb3IgZnV0dXJlIHJlZmVyZW5jZVxuICAgICAgICB0aGF0LmRhdGEucm93X2hlaWdodCA9IHJvd19oZWlnaHQ7XG4gICAgICAgIHRoYXQuZGF0YS50Ym9keV9taW5faGVpZ2h0ID0gbWluX2hlaWdodDtcbiAgICB9XG5cbiAgICAvLyBDbGVhciBmaWx0ZXIgYW5kIHJlc2V0IHRvIHBhZ2UgMVxuICAgIGNsZWFyX2ZpbHRlcigpIHtcbiAgICAgICAgbGV0IHRoYXQgPSB0aGlzO1xuXG4gICAgICAgIHRoYXQuZGF0YS5maWx0ZXIgPSAnJztcblxuICAgICAgICAvLyBDbGVhciB0aGUgZmlsdGVyIGlucHV0XG4gICAgICAgIGNvbnN0ICRmaWx0ZXIgPSB0aGF0LiRpZCgnZmlsdGVyX2lucHV0Jyk7XG4gICAgICAgIGlmICgkZmlsdGVyICYmICRmaWx0ZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgJGZpbHRlci52YWwoJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVsb2FkIGZyb20gcGFnZSAxXG4gICAgICAgIHRoYXQubG9hZF9wYWdlKDEpO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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