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>
248 lines
28 KiB
JavaScript
Executable File
248 lines
28 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Currency_Input
|
|
*
|
|
* Extends Text_Input to provide automatic currency formatting.
|
|
*
|
|
* Features:
|
|
* - Adds thousands separators (commas) every 3 digits
|
|
* - Optional currency symbol prefix (default: hidden)
|
|
* - Optional decimal support (default: disabled)
|
|
* - Smart backspace over formatting characters
|
|
* - No mid-string formatting (waits for blur)
|
|
*
|
|
* Arguments:
|
|
* - $allow_decimals - Allow 2 decimal places (default: false)
|
|
* - $show_symbol - Show currency symbol (default: false)
|
|
* - $currency_symbol - Currency symbol to use (default: "$")
|
|
*
|
|
* Usage:
|
|
* <Currency_Input />
|
|
* <Currency_Input $show_symbol=true />
|
|
* <Currency_Input $allow_decimals=true />
|
|
* <Currency_Input $show_symbol=true $allow_decimals=true $currency_symbol="€" />
|
|
*
|
|
* Behavior:
|
|
* - Type "1234567" -> displays "1,234,567", val() returns "1234567"
|
|
* - Type "1234567.89" (with decimals) -> displays "1,234,567.89", val() returns "1234567.89"
|
|
* - With symbol: displays "$1,234,567", val() still returns "1234567"
|
|
*/
|
|
class Currency_Input extends Text_Input {
|
|
on_create() {
|
|
super.on_create();
|
|
|
|
// Set defaults for options
|
|
if (this.args.allow_decimals === undefined) {
|
|
this.args.allow_decimals = false;
|
|
}
|
|
if (this.args.show_symbol === undefined) {
|
|
this.args.show_symbol = false;
|
|
}
|
|
if (this.args.currency_symbol === undefined) {
|
|
this.args.currency_symbol = '$';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Format currency with commas and optional symbol
|
|
* @param {string} value - Numeric value (may include decimal)
|
|
* @returns {string} Formatted currency string
|
|
*/
|
|
_format_currency(value) {
|
|
if (!value) {
|
|
return '';
|
|
}
|
|
|
|
// Split into integer and decimal parts
|
|
let parts = value.split('.');
|
|
let integer_part = parts[0];
|
|
let decimal_part = parts[1];
|
|
|
|
// Add commas to integer part
|
|
integer_part = integer_part.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
|
|
// Reconstruct with decimal if allowed
|
|
let formatted = integer_part;
|
|
if (this.args.allow_decimals && decimal_part !== undefined) {
|
|
// Limit to 2 decimal places
|
|
decimal_part = decimal_part.substr(0, 2);
|
|
formatted += '.' + decimal_part;
|
|
}
|
|
|
|
// Add currency symbol if enabled
|
|
if (this.args.show_symbol) {
|
|
formatted = this.args.currency_symbol + formatted;
|
|
}
|
|
return formatted;
|
|
}
|
|
|
|
/**
|
|
* Extract numeric value from formatted string
|
|
* @param {string} formatted - Formatted currency string
|
|
* @returns {string} Clean numeric value (digits and decimal only)
|
|
*/
|
|
_get_numeric_value(formatted) {
|
|
if (!formatted) {
|
|
return '';
|
|
}
|
|
|
|
// Remove currency symbol and commas
|
|
let cleaned = formatted.replace(/[^0-9.]/g, '');
|
|
|
|
// Ensure only one decimal point
|
|
const decimal_count = (cleaned.match(/\./g) || []).length;
|
|
if (decimal_count > 1) {
|
|
// Keep only first decimal point
|
|
const first_decimal = cleaned.indexOf('.');
|
|
cleaned = cleaned.substr(0, first_decimal + 1) + cleaned.substr(first_decimal + 1).replace(/\./g, '');
|
|
}
|
|
return cleaned;
|
|
}
|
|
|
|
/**
|
|
* val() - Get or set the currency value
|
|
* Getter returns numeric string (no commas, no symbol)
|
|
* Setter accepts anything and formats with commas/symbol
|
|
* @param {string} [value]
|
|
* @returns {string}
|
|
*/
|
|
val(value) {
|
|
if (arguments.length === 0) {
|
|
// Getter - return numeric value only
|
|
const raw = this.$id('input').val();
|
|
return this._get_numeric_value(raw);
|
|
} else {
|
|
// Setter - format and display
|
|
if (!value) {
|
|
this.data.value = '';
|
|
if (this.$id('input').exists()) {
|
|
this.$id('input').val('');
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Clean the input value
|
|
const numeric = this._get_numeric_value(str(value));
|
|
const formatted = this._format_currency(numeric);
|
|
this.data.value = formatted;
|
|
if (this.$id('input').exists()) {
|
|
this.$id('input').val(formatted);
|
|
}
|
|
}
|
|
}
|
|
on_ready() {
|
|
super.on_ready();
|
|
const $input = this.$id('input');
|
|
|
|
// Handle keydown to intercept backspace at end of string
|
|
$input.on('keydown', e => {
|
|
const raw = $input.val();
|
|
|
|
// Only handle backspace key
|
|
if (e.key !== 'Backspace') {
|
|
return;
|
|
}
|
|
const input_element = $input[0];
|
|
const cursor_pos = input_element.selectionStart;
|
|
const cursor_end = input_element.selectionEnd;
|
|
const value_length = raw.length;
|
|
|
|
// Only handle if cursor is at the end and no selection
|
|
if (cursor_pos === value_length && cursor_pos === cursor_end) {
|
|
// Check if character before cursor is non-numeric
|
|
if (cursor_pos > 0) {
|
|
const char_before = raw.charAt(cursor_pos - 1);
|
|
if (!/[0-9]/.test(char_before)) {
|
|
// Character before cursor is not a digit
|
|
// Delete the last digit instead
|
|
e.preventDefault();
|
|
const numeric = this._get_numeric_value(raw);
|
|
if (numeric.length > 0) {
|
|
// Remove last character from numeric value
|
|
const new_numeric = numeric.substr(0, numeric.length - 1);
|
|
const formatted = this._format_currency(new_numeric);
|
|
$input.val(formatted);
|
|
|
|
// Place cursor at end
|
|
setTimeout(() => {
|
|
const new_length = $input.val().length;
|
|
input_element.setSelectionRange(new_length, new_length);
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle input event for live formatting
|
|
$input.on('input', () => {
|
|
const raw = $input.val();
|
|
const input_element = $input[0];
|
|
const cursor_pos = input_element.selectionStart;
|
|
const value_length = raw.length;
|
|
|
|
// Only apply live formatting if cursor is at the end
|
|
if (cursor_pos === value_length) {
|
|
// Extract numeric value
|
|
let numeric = this._get_numeric_value(raw);
|
|
|
|
// Limit decimal places to 2 if decimals allowed
|
|
if (this.args.allow_decimals) {
|
|
const parts = numeric.split('.');
|
|
if (parts[1] && parts[1].length > 2) {
|
|
numeric = parts[0] + '.' + parts[1].substr(0, 2);
|
|
}
|
|
}
|
|
|
|
// Format the numeric value
|
|
const formatted = this._format_currency(numeric);
|
|
$input.val(formatted);
|
|
} else {
|
|
// Cursor is not at end - user is editing in the middle
|
|
// Don't format, just clean invalid characters
|
|
const numeric = this._get_numeric_value(raw);
|
|
|
|
// Only update if we removed invalid characters
|
|
if (this._format_currency(numeric) !== raw) {
|
|
// Preserve just the numeric characters
|
|
const symbol_offset = this.args.show_symbol ? this.args.currency_symbol.length : 0;
|
|
const cleaned = (this.args.show_symbol ? this.args.currency_symbol : '') + numeric;
|
|
if (cleaned !== raw) {
|
|
$input.val(cleaned);
|
|
// Restore cursor position (approximately)
|
|
const new_cursor = Math.min(cursor_pos, cleaned.length);
|
|
input_element.setSelectionRange(new_cursor, new_cursor);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle blur to reformat when done editing
|
|
$input.on('blur', () => {
|
|
const raw = $input.val();
|
|
if (!raw) {
|
|
return;
|
|
}
|
|
|
|
// Reformat the entire value on blur
|
|
const numeric = this._get_numeric_value(raw);
|
|
const formatted = this._format_currency(numeric);
|
|
$input.val(formatted);
|
|
});
|
|
|
|
// Handle focus to select all for easy replacement
|
|
$input.on('focus', () => {
|
|
setTimeout(() => {
|
|
$input[0].select();
|
|
}, 0);
|
|
});
|
|
|
|
// Initialize formatting if there's a value
|
|
const initial_value = $input.val();
|
|
if (initial_value) {
|
|
this.val(initial_value);
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJDdXJyZW5jeV9JbnB1dCIsIlRleHRfSW5wdXQiLCJvbl9jcmVhdGUiLCJhcmdzIiwiYWxsb3dfZGVjaW1hbHMiLCJ1bmRlZmluZWQiLCJzaG93X3N5bWJvbCIsImN1cnJlbmN5X3N5bWJvbCIsIl9mb3JtYXRfY3VycmVuY3kiLCJ2YWx1ZSIsInBhcnRzIiwic3BsaXQiLCJpbnRlZ2VyX3BhcnQiLCJkZWNpbWFsX3BhcnQiLCJyZXBsYWNlIiwiZm9ybWF0dGVkIiwic3Vic3RyIiwiX2dldF9udW1lcmljX3ZhbHVlIiwiY2xlYW5lZCIsImRlY2ltYWxfY291bnQiLCJtYXRjaCIsImxlbmd0aCIsImZpcnN0X2RlY2ltYWwiLCJpbmRleE9mIiwidmFsIiwiYXJndW1lbnRzIiwicmF3IiwiJGlkIiwiZGF0YSIsImV4aXN0cyIsIm51bWVyaWMiLCJzdHIiLCJvbl9yZWFkeSIsIiRpbnB1dCIsIm9uIiwiZSIsImtleSIsImlucHV0X2VsZW1lbnQiLCJjdXJzb3JfcG9zIiwic2VsZWN0aW9uU3RhcnQiLCJjdXJzb3JfZW5kIiwic2VsZWN0aW9uRW5kIiwidmFsdWVfbGVuZ3RoIiwiY2hhcl9iZWZvcmUiLCJjaGFyQXQiLCJ0ZXN0IiwicHJldmVudERlZmF1bHQiLCJuZXdfbnVtZXJpYyIsInNldFRpbWVvdXQiLCJuZXdfbGVuZ3RoIiwic2V0U2VsZWN0aW9uUmFuZ2UiLCJzeW1ib2xfb2Zmc2V0IiwibmV3X2N1cnNvciIsIk1hdGgiLCJtaW4iLCJzZWxlY3QiLCJpbml0aWFsX3ZhbHVlIl0sInNvdXJjZXMiOlsicnN4L3RoZW1lL2NvbXBvbmVudHMvaW5wdXRzL2N1cnJlbmN5X2lucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ3VycmVuY3lfSW5wdXRcbiAqXG4gKiBFeHRlbmRzIFRleHRfSW5wdXQgdG8gcHJvdmlkZSBhdXRvbWF0aWMgY3VycmVuY3kgZm9ybWF0dGluZy5cbiAqXG4gKiBGZWF0dXJlczpcbiAqIC0gQWRkcyB0aG91c2FuZHMgc2VwYXJhdG9ycyAoY29tbWFzKSBldmVyeSAzIGRpZ2l0c1xuICogLSBPcHRpb25hbCBjdXJyZW5jeSBzeW1ib2wgcHJlZml4IChkZWZhdWx0OiBoaWRkZW4pXG4gKiAtIE9wdGlvbmFsIGRlY2ltYWwgc3VwcG9ydCAoZGVmYXVsdDogZGlzYWJsZWQpXG4gKiAtIFNtYXJ0IGJhY2tzcGFjZSBvdmVyIGZvcm1hdHRpbmcgY2hhcmFjdGVyc1xuICogLSBObyBtaWQtc3RyaW5nIGZvcm1hdHRpbmcgKHdhaXRzIGZvciBibHVyKVxuICpcbiAqIEFyZ3VtZW50czpcbiAqIC0gJGFsbG93X2RlY2ltYWxzIC0gQWxsb3cgMiBkZWNpbWFsIHBsYWNlcyAoZGVmYXVsdDogZmFsc2UpXG4gKiAtICRzaG93X3N5bWJvbCAtIFNob3cgY3VycmVuY3kgc3ltYm9sIChkZWZhdWx0OiBmYWxzZSlcbiAqIC0gJGN1cnJlbmN5X3N5bWJvbCAtIEN1cnJlbmN5IHN5bWJvbCB0byB1c2UgKGRlZmF1bHQ6IFwiJFwiKVxuICpcbiAqIFVzYWdlOlxuICogICA8Q3VycmVuY3lfSW5wdXQgLz5cbiAqICAgPEN1cnJlbmN5X0lucHV0ICRzaG93X3N5bWJvbD10cnVlIC8+XG4gKiAgIDxDdXJyZW5jeV9JbnB1dCAkYWxsb3dfZGVjaW1hbHM9dHJ1ZSAvPlxuICogICA8Q3VycmVuY3lfSW5wdXQgJHNob3dfc3ltYm9sPXRydWUgJGFsbG93X2RlY2ltYWxzPXRydWUgJGN1cnJlbmN5X3N5bWJvbD1cIuKCrFwiIC8+XG4gKlxuICogQmVoYXZpb3I6XG4gKiAtIFR5cGUgXCIxMjM0NTY3XCIgLT4gZGlzcGxheXMgXCIxLDIzNCw1NjdcIiwgdmFsKCkgcmV0dXJucyBcIjEyMzQ1NjdcIlxuICogLSBUeXBlIFwiMTIzNDU2Ny44OVwiICh3aXRoIGRlY2ltYWxzKSAtPiBkaXNwbGF5cyBcIjEsMjM0LDU2Ny44OVwiLCB2YWwoKSByZXR1cm5zIFwiMTIzNDU2Ny44OVwiXG4gKiAtIFdpdGggc3ltYm9sOiBkaXNwbGF5cyBcIiQxLDIzNCw1NjdcIiwgdmFsKCkgc3RpbGwgcmV0dXJucyBcIjEyMzQ1NjdcIlxuICovXG5jbGFzcyBDdXJyZW5jeV9JbnB1dCBleHRlbmRzIFRleHRfSW5wdXQge1xuICAgIG9uX2NyZWF0ZSgpIHtcbiAgICAgICAgc3VwZXIub25fY3JlYXRlKCk7XG5cbiAgICAgICAgLy8gU2V0IGRlZmF1bHRzIGZvciBvcHRpb25zXG4gICAgICAgIGlmICh0aGlzLmFyZ3MuYWxsb3dfZGVjaW1hbHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5hcmdzLmFsbG93X2RlY2ltYWxzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYXJncy5zaG93X3N5bWJvbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmFyZ3Muc2hvd19zeW1ib2wgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5hcmdzLmN1cnJlbmN5X3N5bWJvbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmFyZ3MuY3VycmVuY3lfc3ltYm9sID0gJyQnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9ybWF0IGN1cnJlbmN5IHdpdGggY29tbWFzIGFuZCBvcHRpb25hbCBzeW1ib2xcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBOdW1lcmljIHZhbHVlIChtYXkgaW5jbHVkZSBkZWNpbWFsKVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEZvcm1hdHRlZCBjdXJyZW5jeSBzdHJpbmdcbiAgICAgKi9cbiAgICBfZm9ybWF0X2N1cnJlbmN5KHZhbHVlKSB7XG4gICAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwbGl0IGludG8gaW50ZWdlciBhbmQgZGVjaW1hbCBwYXJ0c1xuICAgICAgICBsZXQgcGFydHMgPSB2YWx1ZS5zcGxpdCgnLicpO1xuICAgICAgICBsZXQgaW50ZWdlcl9wYXJ0ID0gcGFydHNbMF07XG4gICAgICAgIGxldCBkZWNpbWFsX3BhcnQgPSBwYXJ0c1sxXTtcblxuICAgICAgICAvLyBBZGQgY29tbWFzIHRvIGludGVnZXIgcGFydFxuICAgICAgICBpbnRlZ2VyX3BhcnQgPSBpbnRlZ2VyX3BhcnQucmVwbGFjZSgvXFxCKD89KFxcZHszfSkrKD8hXFxkKSkvZywgJywnKTtcblxuICAgICAgICAvLyBSZWNvbnN0cnVjdCB3aXRoIGRlY2ltYWwgaWYgYWxsb3dlZFxuICAgICAgICBsZXQgZm9ybWF0dGVkID0gaW50ZWdlcl9wYXJ0O1xuICAgICAgICBpZiAodGhpcy5hcmdzLmFsbG93X2RlY2ltYWxzICYmIGRlY2ltYWxfcGFydCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBMaW1pdCB0byAyIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgICAgICBkZWNpbWFsX3BhcnQgPSBkZWNpbWFsX3BhcnQuc3Vic3RyKDAsIDIpO1xuICAgICAgICAgICAgZm9ybWF0dGVkICs9ICcuJyArIGRlY2ltYWxfcGFydDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBjdXJyZW5jeSBzeW1ib2wgaWYgZW5hYmxlZFxuICAgICAgICBpZiAodGhpcy5hcmdzLnNob3dfc3ltYm9sKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWQgPSB0aGlzLmFyZ3MuY3VycmVuY3lfc3ltYm9sICsgZm9ybWF0dGVkO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0IG51bWVyaWMgdmFsdWUgZnJvbSBmb3JtYXR0ZWQgc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdHRlZCAtIEZvcm1hdHRlZCBjdXJyZW5jeSBzdHJpbmdcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBDbGVhbiBudW1lcmljIHZhbHVlIChkaWdpdHMgYW5kIGRlY2ltYWwgb25seSlcbiAgICAgKi9cbiAgICBfZ2V0X251bWVyaWNfdmFsdWUoZm9ybWF0dGVkKSB7XG4gICAgICAgIGlmICghZm9ybWF0dGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgY3VycmVuY3kgc3ltYm9sIGFuZCBjb21tYXNcbiAgICAgICAgbGV0IGNsZWFuZWQgPSBmb3JtYXR0ZWQucmVwbGFjZSgvW14wLTkuXS9nLCAnJyk7XG5cbiAgICAgICAgLy8gRW5zdXJlIG9ubHkgb25lIGRlY2ltYWwgcG9pbnRcbiAgICAgICAgY29uc3QgZGVjaW1hbF9jb3VudCA9IChjbGVhbmVkLm1hdGNoKC9cXC4vZykgfHwgW10pLmxlbmd0aDtcbiAgICAgICAgaWYgKGRlY2ltYWxfY291bnQgPiAxKSB7XG4gICAgICAgICAgICAvLyBLZWVwIG9ubHkgZmlyc3QgZGVjaW1hbCBwb2ludFxuICAgICAgICAgICAgY29uc3QgZmlyc3RfZGVjaW1hbCA9IGNsZWFuZWQuaW5kZXhPZignLicpO1xuICAgICAgICAgICAgY2xlYW5lZCA9IGNsZWFuZWQuc3Vic3RyKDAsIGZpcnN0X2RlY2ltYWwgKyAxKSArIGNsZWFuZWQuc3Vic3RyKGZpcnN0X2RlY2ltYWwgKyAxKS5yZXBsYWNlKC9cXC4vZywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNsZWFuZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogdmFsKCkgLSBHZXQgb3Igc2V0IHRoZSBjdXJyZW5jeSB2YWx1ZVxuICAgICAqIEdldHRlciByZXR1cm5zIG51bWVyaWMgc3RyaW5nIChubyBjb21tYXMsIG5vIHN5bWJvbClcbiAgICAgKiBTZXR0ZXIgYWNjZXB0cyBhbnl0aGluZyBhbmQgZm9ybWF0cyB3aXRoIGNvbW1hcy9zeW1ib2xcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ZhbHVlXVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdmFsKHZhbHVlKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAvLyBHZXR0ZXIgLSByZXR1cm4gbnVtZXJpYyB2YWx1ZSBvbmx5XG4gICAgICAgICAgICBjb25zdCByYXcgPSB0aGlzLiRpZCgnaW5wdXQnKS52YWwoKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9nZXRfbnVtZXJpY192YWx1ZShyYXcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gU2V0dGVyIC0gZm9ybWF0IGFuZCBkaXNwbGF5XG4gICAgICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhLnZhbHVlID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuJGlkKCdpbnB1dCcpLmV4aXN0cygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGlkKCdpbnB1dCcpLnZhbCgnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2xlYW4gdGhlIGlucHV0IHZhbHVlXG4gICAgICAgICAgICBjb25zdCBudW1lcmljID0gdGhpcy5fZ2V0X251bWVyaWNfdmFsdWUoc3RyKHZhbHVlKSk7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXR0ZWQgPSB0aGlzLl9mb3JtYXRfY3VycmVuY3kobnVtZXJpYyk7XG5cbiAgICAgICAgICAgIHRoaXMuZGF0YS52YWx1ZSA9IGZvcm1hdHRlZDtcbiAgICAgICAgICAgIGlmICh0aGlzLiRpZCgnaW5wdXQnKS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGlkKCdpbnB1dCcpLnZhbChmb3JtYXR0ZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25fcmVhZHkoKSB7XG4gICAgICAgIHN1cGVyLm9uX3JlYWR5KCk7XG5cbiAgICAgICAgY29uc3QgJGlucHV0ID0gdGhpcy4kaWQoJ2lucHV0Jyk7XG5cbiAgICAgICAgLy8gSGFuZGxlIGtleWRvd24gdG8gaW50ZXJjZXB0IGJhY2tzcGFjZSBhdCBlbmQgb2Ygc3RyaW5nXG4gICAgICAgICRpbnB1dC5vbigna2V5ZG93bicsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGJhY2tzcGFjZSBrZXlcbiAgICAgICAgICAgIGlmIChlLmtleSAhPT0gJ0JhY2tzcGFjZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGlucHV0X2VsZW1lbnQgPSAkaW5wdXRbMF07XG4gICAgICAgICAgICBjb25zdCBjdXJzb3JfcG9zID0gaW5wdXRfZWxlbWVudC5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgIGNvbnN0IGN1cnNvcl9lbmQgPSBpbnB1dF9lbGVtZW50LnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlX2xlbmd0aCA9IHJhdy5sZW5ndGg7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGlmIGN1cnNvciBpcyBhdCB0aGUgZW5kIGFuZCBubyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmIChjdXJzb3JfcG9zID09PSB2YWx1ZV9sZW5ndGggJiYgY3Vyc29yX3BvcyA9PT0gY3Vyc29yX2VuZCkge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGNoYXJhY3RlciBiZWZvcmUgY3Vyc29yIGlzIG5vbi1udW1lcmljXG4gICAgICAgICAgICAgICAgaWYgKGN1cnNvcl9wb3MgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXJfYmVmb3JlID0gcmF3LmNoYXJBdChjdXJzb3JfcG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghL1swLTldLy50ZXN0KGNoYXJfYmVmb3JlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hhcmFjdGVyIGJlZm9yZSBjdXJzb3IgaXMgbm90IGEgZGlnaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGV0ZSB0aGUgbGFzdCBkaWdpdCBpbnN0ZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG51bWVyaWMgPSB0aGlzLl9nZXRfbnVtZXJpY192YWx1ZShyYXcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bWVyaWMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBsYXN0IGNoYXJhY3RlciBmcm9tIG51bWVyaWMgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdfbnVtZXJpYyA9IG51bWVyaWMuc3Vic3RyKDAsIG51bWVyaWMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gdGhpcy5fZm9ybWF0X2N1cnJlbmN5KG5ld19udW1lcmljKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKGZvcm1hdHRlZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjdXJzb3IgYXQgZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld19sZW5ndGggPSAkaW5wdXQudmFsKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9lbGVtZW50LnNldFNlbGVjdGlvblJhbmdlKG5ld19sZW5ndGgsIG5ld19sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgaW5wdXQgZXZlbnQgZm9yIGxpdmUgZm9ybWF0dGluZ1xuICAgICAgICAkaW5wdXQub24oJ2lucHV0JywgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmF3ID0gJGlucHV0LnZhbCgpO1xuICAgICAgICAgICAgY29uc3QgaW5wdXRfZWxlbWVudCA9ICRpbnB1dFswXTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnNvcl9wb3MgPSBpbnB1dF9lbGVtZW50LnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgY29uc3QgdmFsdWVfbGVuZ3RoID0gcmF3Lmxlbmd0aDtcblxuICAgICAgICAgICAgLy8gT25seSBhcHBseSBsaXZlIGZvcm1hdHRpbmcgaWYgY3Vyc29yIGlzIGF0IHRoZSBlbmRcbiAgICAgICAgICAgIGlmIChjdXJzb3JfcG9zID09PSB2YWx1ZV9sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IG51bWVyaWMgdmFsdWVcbiAgICAgICAgICAgICAgICBsZXQgbnVtZXJpYyA9IHRoaXMuX2dldF9udW1lcmljX3ZhbHVlKHJhdyk7XG5cbiAgICAgICAgICAgICAgICAvLyBMaW1pdCBkZWNpbWFsIHBsYWNlcyB0byAyIGlmIGRlY2ltYWxzIGFsbG93ZWRcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5hcmdzLmFsbG93X2RlY2ltYWxzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gbnVtZXJpYy5zcGxpdCgnLicpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFydHNbMV0gJiYgcGFydHNbMV0ubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtZXJpYyA9IHBhcnRzWzBdICsgJy4nICsgcGFydHNbMV0uc3Vic3RyKDAsIDIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gRm9ybWF0IHRoZSBudW1lcmljIHZhbHVlXG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gdGhpcy5fZm9ybWF0X2N1cnJlbmN5KG51bWVyaWMpO1xuICAgICAgICAgICAgICAgICRpbnB1dC52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ3Vyc29yIGlzIG5vdCBhdCBlbmQgLSB1c2VyIGlzIGVkaXRpbmcgaW4gdGhlIG1pZGRsZVxuICAgICAgICAgICAgICAgIC8vIERvbid0IGZvcm1hdCwganVzdCBjbGVhbiBpbnZhbGlkIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgICBjb25zdCBudW1lcmljID0gdGhpcy5fZ2V0X251bWVyaWNfdmFsdWUocmF3KTtcblxuICAgICAgICAgICAgICAgIC8vIE9ubHkgdXBkYXRlIGlmIHdlIHJlbW92ZWQgaW52YWxpZCBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2Zvcm1hdF9jdXJyZW5jeShudW1lcmljKSAhPT0gcmF3KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFByZXNlcnZlIGp1c3QgdGhlIG51bWVyaWMgY2hhcmFjdGVyc1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzeW1ib2xfb2Zmc2V0ID0gdGhpcy5hcmdzLnNob3dfc3ltYm9sID8gdGhpcy5hcmdzLmN1cnJlbmN5X3N5bWJvbC5sZW5ndGggOiAwO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGVhbmVkID0gKHRoaXMuYXJncy5zaG93X3N5bWJvbCA/IHRoaXMuYXJncy5jdXJyZW5jeV9zeW1ib2wgOiAnJykgKyBudW1lcmljO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjbGVhbmVkICE9PSByYXcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwoY2xlYW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXN0b3JlIGN1cnNvciBwb3NpdGlvbiAoYXBwcm94aW1hdGVseSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld19jdXJzb3IgPSBNYXRoLm1pbihjdXJzb3JfcG9zLCBjbGVhbmVkLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9lbGVtZW50LnNldFNlbGVjdGlvblJhbmdlKG5ld19jdXJzb3IsIG5ld19jdXJzb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgYmx1ciB0byByZWZvcm1hdCB3aGVuIGRvbmUgZWRpdGluZ1xuICAgICAgICAkaW5wdXQub24oJ2JsdXInLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIGlmICghcmF3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZWZvcm1hdCB0aGUgZW50aXJlIHZhbHVlIG9uIGJsdXJcbiAgICAgICAgICAgIGNvbnN0IG51bWVyaWMgPSB0aGlzLl9nZXRfbnVtZXJpY192YWx1ZShyYXcpO1xuICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gdGhpcy5fZm9ybWF0X2N1cnJlbmN5KG51bWVyaWMpO1xuICAgICAgICAgICAgJGlucHV0LnZhbChmb3JtYXR0ZWQpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgZm9jdXMgdG8gc2VsZWN0IGFsbCBmb3IgZWFzeSByZXBsYWNlbWVudFxuICAgICAgICAkaW5wdXQub24oJ2ZvY3VzJywgKCkgPT4ge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgJGlucHV0WzBdLnNlbGVjdCgpO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgZm9ybWF0dGluZyBpZiB0aGVyZSdzIGEgdmFsdWVcbiAgICAgICAgY29uc3QgaW5pdGlhbF92YWx1ZSA9ICRpbnB1dC52YWwoKTtcbiAgICAgICAgaWYgKGluaXRpYWxfdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMudmFsKGluaXRpYWxfdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTUEsY0FBYyxTQUFTQyxVQUFVLENBQUM7RUFDcENDLFNBQVNBLENBQUEsRUFBRztJQUNSLEtBQUssQ0FBQ0EsU0FBUyxDQUFDLENBQUM7O0lBRWpCO0lBQ0EsSUFBSSxJQUFJLENBQUNDLElBQUksQ0FBQ0MsY0FBYyxLQUFLQyxTQUFTLEVBQUU7TUFDeEMsSUFBSSxDQUFDRixJQUFJLENBQUNDLGNBQWMsR0FBRyxLQUFLO0lBQ3BDO0lBQ0EsSUFBSSxJQUFJLENBQUNELElBQUksQ0FBQ0csV0FBVyxLQUFLRCxTQUFTLEVBQUU7TUFDckMsSUFBSSxDQUFDRixJQUFJLENBQUNHLFdBQVcsR0FBRyxLQUFLO0lBQ2pDO0lBQ0EsSUFBSSxJQUFJLENBQUNILElBQUksQ0FBQ0ksZUFBZSxLQUFLRixTQUFTLEVBQUU7TUFDekMsSUFBSSxDQUFDRixJQUFJLENBQUNJLGVBQWUsR0FBRyxHQUFHO0lBQ25DO0VBQ0o7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJQyxnQkFBZ0JBLENBQUNDLEtBQUssRUFBRTtJQUNwQixJQUFJLENBQUNBLEtBQUssRUFBRTtNQUNSLE9BQU8sRUFBRTtJQUNiOztJQUVBO0lBQ0EsSUFBSUMsS0FBSyxHQUFHRCxLQUFLLENBQUNFLEtBQUssQ0FBQyxHQUFHLENBQUM7SUFD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
|