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>
244 lines
29 KiB
JavaScript
Executable File
244 lines
29 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Phone_Text_Input
|
|
*
|
|
* Extends Text_Input to provide automatic phone number formatting.
|
|
*
|
|
* Features:
|
|
* - US Mode (default): Formats as (XXX) XXX-XXXX on every keystroke
|
|
* - International Mode: Triggered by starting with '+', disables formatting
|
|
* - val() getter returns formatted string as displayed
|
|
* - val() setter accepts any format and displays appropriately
|
|
*
|
|
* Usage:
|
|
* <Phone_Text_Input $placeholder="Phone number" />
|
|
*
|
|
* Behavior:
|
|
* - Type "5551234567" -> displays "(555) 123-4567", val() returns "(555) 123-4567"
|
|
* - Type "+44 20 7123 4567" -> displays as typed, val() returns "+44 20 7123 4567"
|
|
* - Leading "1" is stripped: "15551234567" -> "(555) 123-4567"
|
|
*/
|
|
class Phone_Text_Input extends Text_Input {
|
|
on_create() {
|
|
super.on_create();
|
|
this._is_international = false;
|
|
}
|
|
|
|
/**
|
|
* Check if input is in international mode (starts with +)
|
|
* @param {string} value
|
|
* @returns {boolean}
|
|
*/
|
|
_check_international_mode(value) {
|
|
return value && str(value).charAt(0) === '+';
|
|
}
|
|
|
|
/**
|
|
* Format US phone number as (XXX) XXX-XXXX
|
|
* @param {string} digits - Clean numeric string (should be 10 digits or less after processing)
|
|
* @returns {string} Formatted phone number
|
|
*/
|
|
_format_us_phone(digits) {
|
|
// Format based on length (assumes digits are already cleaned and limited to 10)
|
|
if (digits.length >= 6) {
|
|
// (XXX) XXX-XXXX
|
|
return '(' + digits.substr(0, 3) + ') ' + digits.substr(3, 3) + '-' + digits.substr(6);
|
|
} else if (digits.length >= 3) {
|
|
// (XXX) XXX
|
|
return '(' + digits.substr(0, 3) + ') ' + digits.substr(3);
|
|
} else if (digits.length > 0) {
|
|
// (XX
|
|
return '(' + digits;
|
|
}
|
|
return digits;
|
|
}
|
|
|
|
/**
|
|
* val() - Get or set the phone number
|
|
* Getter returns formatted value as displayed (with parens, dashes, etc)
|
|
* Setter accepts anything and formats appropriately
|
|
* @param {string} [value]
|
|
* @returns {string}
|
|
*/
|
|
val(value) {
|
|
if (arguments.length === 0) {
|
|
// Getter - return the formatted value as displayed
|
|
return this.$id('input').val() || '';
|
|
} else {
|
|
// Setter - format and display
|
|
if (!value) {
|
|
this.data.value = '';
|
|
if (this.$id('input').exists()) {
|
|
this.$id('input').val('');
|
|
}
|
|
return;
|
|
}
|
|
const str_value = str(value);
|
|
if (this._check_international_mode(str_value)) {
|
|
// International mode - no formatting
|
|
this.data.value = str_value;
|
|
if (this.$id('input').exists()) {
|
|
this.$id('input').val(str_value);
|
|
}
|
|
} else {
|
|
// US mode - clean digits and format
|
|
const digits = str_value.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Strip US country code
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// Take first 10
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// Use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
this.data.value = formatted;
|
|
if (this.$id('input').exists()) {
|
|
this.$id('input').val(formatted);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
on_ready() {
|
|
super.on_ready();
|
|
const $input = this.$id('input');
|
|
let _last_cursor_position = null;
|
|
|
|
// Handle keydown to intercept backspace at end of string
|
|
$input.on('keydown', e => {
|
|
const raw = $input.val();
|
|
|
|
// Skip if international mode
|
|
if (this._check_international_mode(raw)) {
|
|
return;
|
|
}
|
|
|
|
// 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 digits = raw.replace(/[^0-9]/g, '');
|
|
if (digits.length > 0) {
|
|
const new_digits = digits.substr(0, digits.length - 1);
|
|
const formatted = this._format_us_phone(new_digits);
|
|
$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();
|
|
if (this._check_international_mode(raw)) {
|
|
// International mode - allow anything
|
|
this._is_international = true;
|
|
// No formatting, no restrictions
|
|
return;
|
|
}
|
|
|
|
// US mode
|
|
this._is_international = false;
|
|
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) {
|
|
// Remove any non-digit, non-formatting characters
|
|
const cleaned = raw.replace(/[^0-9\s\-()]/g, '');
|
|
const digits = cleaned.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Exactly 11 digits starting with "1" followed by valid area code digit (2-9)
|
|
// This is a US country code - strip the leading 1
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// More than 10 digits - just take the first 10 and ignore the rest
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// 10 or fewer digits - use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
|
|
// Format the digits
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
$input.val(formatted);
|
|
} else {
|
|
// Cursor is not at end - user is editing in the middle
|
|
// Don't format, just clean invalid characters
|
|
const cleaned = raw.replace(/[^0-9\s\-()]/g, '');
|
|
if (cleaned !== raw) {
|
|
$input.val(cleaned);
|
|
// Restore cursor position
|
|
input_element.setSelectionRange(cursor_pos, cursor_pos);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle blur to reformat when done editing
|
|
$input.on('blur', () => {
|
|
const raw = $input.val();
|
|
|
|
// Skip if international mode or empty
|
|
if (this._check_international_mode(raw) || !raw) {
|
|
return;
|
|
}
|
|
|
|
// Reformat the entire value on blur
|
|
const digits = raw.replace(/[^0-9]/g, '');
|
|
|
|
// Determine which digits to format
|
|
let digits_to_format;
|
|
if (digits.length === 11 && digits.charAt(0) === '1' && /[2-9]/.test(digits.charAt(1))) {
|
|
// Exactly 11 digits starting with "1" followed by valid area code digit (2-9)
|
|
// This is a US country code - strip the leading 1
|
|
digits_to_format = digits.substr(1);
|
|
} else if (digits.length > 10) {
|
|
// More than 10 digits - just take the first 10
|
|
digits_to_format = digits.substr(0, 10);
|
|
} else {
|
|
// 10 or fewer digits - use as-is
|
|
digits_to_format = digits;
|
|
}
|
|
const formatted = this._format_us_phone(digits_to_format);
|
|
$input.val(formatted);
|
|
});
|
|
|
|
// 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQaG9uZV9UZXh0X0lucHV0IiwiVGV4dF9JbnB1dCIsIm9uX2NyZWF0ZSIsIl9pc19pbnRlcm5hdGlvbmFsIiwiX2NoZWNrX2ludGVybmF0aW9uYWxfbW9kZSIsInZhbHVlIiwic3RyIiwiY2hhckF0IiwiX2Zvcm1hdF91c19waG9uZSIsImRpZ2l0cyIsImxlbmd0aCIsInN1YnN0ciIsInZhbCIsImFyZ3VtZW50cyIsIiRpZCIsImRhdGEiLCJleGlzdHMiLCJzdHJfdmFsdWUiLCJyZXBsYWNlIiwiZGlnaXRzX3RvX2Zvcm1hdCIsInRlc3QiLCJmb3JtYXR0ZWQiLCJvbl9yZWFkeSIsIiRpbnB1dCIsIl9sYXN0X2N1cnNvcl9wb3NpdGlvbiIsIm9uIiwiZSIsInJhdyIsImtleSIsImlucHV0X2VsZW1lbnQiLCJjdXJzb3JfcG9zIiwic2VsZWN0aW9uU3RhcnQiLCJjdXJzb3JfZW5kIiwic2VsZWN0aW9uRW5kIiwidmFsdWVfbGVuZ3RoIiwiY2hhcl9iZWZvcmUiLCJwcmV2ZW50RGVmYXVsdCIsIm5ld19kaWdpdHMiLCJzZXRUaW1lb3V0IiwibmV3X2xlbmd0aCIsInNldFNlbGVjdGlvblJhbmdlIiwiY2xlYW5lZCIsImluaXRpYWxfdmFsdWUiXSwic291cmNlcyI6WyJyc3gvdGhlbWUvY29tcG9uZW50cy9pbnB1dHMvcGhvbmVfdGV4dF9pbnB1dC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBob25lX1RleHRfSW5wdXRcbiAqXG4gKiBFeHRlbmRzIFRleHRfSW5wdXQgdG8gcHJvdmlkZSBhdXRvbWF0aWMgcGhvbmUgbnVtYmVyIGZvcm1hdHRpbmcuXG4gKlxuICogRmVhdHVyZXM6XG4gKiAtIFVTIE1vZGUgKGRlZmF1bHQpOiBGb3JtYXRzIGFzIChYWFgpIFhYWC1YWFhYIG9uIGV2ZXJ5IGtleXN0cm9rZVxuICogLSBJbnRlcm5hdGlvbmFsIE1vZGU6IFRyaWdnZXJlZCBieSBzdGFydGluZyB3aXRoICcrJywgZGlzYWJsZXMgZm9ybWF0dGluZ1xuICogLSB2YWwoKSBnZXR0ZXIgcmV0dXJucyBmb3JtYXR0ZWQgc3RyaW5nIGFzIGRpc3BsYXllZFxuICogLSB2YWwoKSBzZXR0ZXIgYWNjZXB0cyBhbnkgZm9ybWF0IGFuZCBkaXNwbGF5cyBhcHByb3ByaWF0ZWx5XG4gKlxuICogVXNhZ2U6XG4gKiAgIDxQaG9uZV9UZXh0X0lucHV0ICRwbGFjZWhvbGRlcj1cIlBob25lIG51bWJlclwiIC8+XG4gKlxuICogQmVoYXZpb3I6XG4gKiAtIFR5cGUgXCI1NTUxMjM0NTY3XCIgLT4gZGlzcGxheXMgXCIoNTU1KSAxMjMtNDU2N1wiLCB2YWwoKSByZXR1cm5zIFwiKDU1NSkgMTIzLTQ1NjdcIlxuICogLSBUeXBlIFwiKzQ0IDIwIDcxMjMgNDU2N1wiIC0+IGRpc3BsYXlzIGFzIHR5cGVkLCB2YWwoKSByZXR1cm5zIFwiKzQ0IDIwIDcxMjMgNDU2N1wiXG4gKiAtIExlYWRpbmcgXCIxXCIgaXMgc3RyaXBwZWQ6IFwiMTU1NTEyMzQ1NjdcIiAtPiBcIig1NTUpIDEyMy00NTY3XCJcbiAqL1xuY2xhc3MgUGhvbmVfVGV4dF9JbnB1dCBleHRlbmRzIFRleHRfSW5wdXQge1xuICAgIG9uX2NyZWF0ZSgpIHtcbiAgICAgICAgc3VwZXIub25fY3JlYXRlKCk7XG4gICAgICAgIHRoaXMuX2lzX2ludGVybmF0aW9uYWwgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBpbnB1dCBpcyBpbiBpbnRlcm5hdGlvbmFsIG1vZGUgKHN0YXJ0cyB3aXRoICspXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX2NoZWNrX2ludGVybmF0aW9uYWxfbW9kZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgJiYgc3RyKHZhbHVlKS5jaGFyQXQoMCkgPT09ICcrJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXQgVVMgcGhvbmUgbnVtYmVyIGFzIChYWFgpIFhYWC1YWFhYXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRpZ2l0cyAtIENsZWFuIG51bWVyaWMgc3RyaW5nIChzaG91bGQgYmUgMTAgZGlnaXRzIG9yIGxlc3MgYWZ0ZXIgcHJvY2Vzc2luZylcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBGb3JtYXR0ZWQgcGhvbmUgbnVtYmVyXG4gICAgICovXG4gICAgX2Zvcm1hdF91c19waG9uZShkaWdpdHMpIHtcbiAgICAgICAgLy8gRm9ybWF0IGJhc2VkIG9uIGxlbmd0aCAoYXNzdW1lcyBkaWdpdHMgYXJlIGFscmVhZHkgY2xlYW5lZCBhbmQgbGltaXRlZCB0byAxMClcbiAgICAgICAgaWYgKGRpZ2l0cy5sZW5ndGggPj0gNikge1xuICAgICAgICAgICAgLy8gKFhYWCkgWFhYLVhYWFhcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBkaWdpdHMuc3Vic3RyKDAsIDMpICsgJykgJyArIGRpZ2l0cy5zdWJzdHIoMywgMykgKyAnLScgKyBkaWdpdHMuc3Vic3RyKDYpO1xuICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPj0gMykge1xuICAgICAgICAgICAgLy8gKFhYWCkgWFhYXG4gICAgICAgICAgICByZXR1cm4gJygnICsgZGlnaXRzLnN1YnN0cigwLCAzKSArICcpICcgKyBkaWdpdHMuc3Vic3RyKDMpO1xuICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAvLyAoWFhcbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBkaWdpdHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGlnaXRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHZhbCgpIC0gR2V0IG9yIHNldCB0aGUgcGhvbmUgbnVtYmVyXG4gICAgICogR2V0dGVyIHJldHVybnMgZm9ybWF0dGVkIHZhbHVlIGFzIGRpc3BsYXllZCAod2l0aCBwYXJlbnMsIGRhc2hlcywgZXRjKVxuICAgICAqIFNldHRlciBhY2NlcHRzIGFueXRoaW5nIGFuZCBmb3JtYXRzIGFwcHJvcHJpYXRlbHlcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ZhbHVlXVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdmFsKHZhbHVlKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAvLyBHZXR0ZXIgLSByZXR1cm4gdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBkaXNwbGF5ZWRcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRpZCgnaW5wdXQnKS52YWwoKSB8fCAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNldHRlciAtIGZvcm1hdCBhbmQgZGlzcGxheVxuICAgICAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YS52YWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRpZCgnaW5wdXQnKS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRpZCgnaW5wdXQnKS52YWwoJycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHN0cl92YWx1ZSA9IHN0cih2YWx1ZSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9jaGVja19pbnRlcm5hdGlvbmFsX21vZGUoc3RyX3ZhbHVlKSkge1xuICAgICAgICAgICAgICAgIC8vIEludGVybmF0aW9uYWwgbW9kZSAtIG5vIGZvcm1hdHRpbmdcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEudmFsdWUgPSBzdHJfdmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuJGlkKCdpbnB1dCcpLmV4aXN0cygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGlkKCdpbnB1dCcpLnZhbChzdHJfdmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVVMgbW9kZSAtIGNsZWFuIGRpZ2l0cyBhbmQgZm9ybWF0XG4gICAgICAgICAgICAgICAgY29uc3QgZGlnaXRzID0gc3RyX3ZhbHVlLnJlcGxhY2UoL1teMC05XS9nLCAnJyk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZXRlcm1pbmUgd2hpY2ggZGlnaXRzIHRvIGZvcm1hdFxuICAgICAgICAgICAgICAgIGxldCBkaWdpdHNfdG9fZm9ybWF0O1xuICAgICAgICAgICAgICAgIGlmIChkaWdpdHMubGVuZ3RoID09PSAxMSAmJiBkaWdpdHMuY2hhckF0KDApID09PSAnMScgJiYgL1syLTldLy50ZXN0KGRpZ2l0cy5jaGFyQXQoMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN0cmlwIFVTIGNvdW50cnkgY29kZVxuICAgICAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRpZ2l0cy5sZW5ndGggPiAxMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUYWtlIGZpcnN0IDEwXG4gICAgICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHMuc3Vic3RyKDAsIDEwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgYXMtaXNcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzX3RvX2Zvcm1hdCA9IGRpZ2l0cztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBmb3JtYXR0ZWQgPSB0aGlzLl9mb3JtYXRfdXNfcGhvbmUoZGlnaXRzX3RvX2Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhLnZhbHVlID0gZm9ybWF0dGVkO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLiRpZCgnaW5wdXQnKS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiRpZCgnaW5wdXQnKS52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbl9yZWFkeSgpIHtcbiAgICAgICAgc3VwZXIub25fcmVhZHkoKTtcblxuICAgICAgICBjb25zdCAkaW5wdXQgPSB0aGlzLiRpZCgnaW5wdXQnKTtcbiAgICAgICAgbGV0IF9sYXN0X2N1cnNvcl9wb3NpdGlvbiA9IG51bGw7XG5cbiAgICAgICAgLy8gSGFuZGxlIGtleWRvd24gdG8gaW50ZXJjZXB0IGJhY2tzcGFjZSBhdCBlbmQgb2Ygc3RyaW5nXG4gICAgICAgICRpbnB1dC5vbigna2V5ZG93bicsIChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIC8vIFNraXAgaWYgaW50ZXJuYXRpb25hbCBtb2RlXG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGJhY2tzcGFjZSBrZXlcbiAgICAgICAgICAgIGlmIChlLmtleSAhPT0gJ0JhY2tzcGFjZScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGlucHV0X2VsZW1lbnQgPSAkaW5wdXRbMF07XG4gICAgICAgICAgICBjb25zdCBjdXJzb3JfcG9zID0gaW5wdXRfZWxlbWVudC5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgIGNvbnN0IGN1cnNvcl9lbmQgPSBpbnB1dF9lbGVtZW50LnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlX2xlbmd0aCA9IHJhdy5sZW5ndGg7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGlmIGN1cnNvciBpcyBhdCB0aGUgZW5kIGFuZCBubyBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmIChjdXJzb3JfcG9zID09PSB2YWx1ZV9sZW5ndGggJiYgY3Vyc29yX3BvcyA9PT0gY3Vyc29yX2VuZCkge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGNoYXJhY3RlciBiZWZvcmUgY3Vyc29yIGlzIG5vbi1udW1lcmljXG4gICAgICAgICAgICAgICAgaWYgKGN1cnNvcl9wb3MgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXJfYmVmb3JlID0gcmF3LmNoYXJBdChjdXJzb3JfcG9zIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghL1swLTldLy50ZXN0KGNoYXJfYmVmb3JlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hhcmFjdGVyIGJlZm9yZSBjdXJzb3IgaXMgbm90IGEgZGlnaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGV0ZSB0aGUgbGFzdCBkaWdpdCBpbnN0ZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpZ2l0cyA9IHJhdy5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpZ2l0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3X2RpZ2l0cyA9IGRpZ2l0cy5zdWJzdHIoMCwgZGlnaXRzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvcm1hdHRlZCA9IHRoaXMuX2Zvcm1hdF91c19waG9uZShuZXdfZGlnaXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5wdXQudmFsKGZvcm1hdHRlZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjdXJzb3IgYXQgZW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld19sZW5ndGggPSAkaW5wdXQudmFsKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9lbGVtZW50LnNldFNlbGVjdGlvblJhbmdlKG5ld19sZW5ndGgsIG5ld19sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgaW5wdXQgZXZlbnQgZm9yIGxpdmUgZm9ybWF0dGluZ1xuICAgICAgICAkaW5wdXQub24oJ2lucHV0JywgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmF3ID0gJGlucHV0LnZhbCgpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykpIHtcbiAgICAgICAgICAgICAgICAvLyBJbnRlcm5hdGlvbmFsIG1vZGUgLSBhbGxvdyBhbnl0aGluZ1xuICAgICAgICAgICAgICAgIHRoaXMuX2lzX2ludGVybmF0aW9uYWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgIC8vIE5vIGZvcm1hdHRpbmcsIG5vIHJlc3RyaWN0aW9uc1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVVMgbW9kZVxuICAgICAgICAgICAgdGhpcy5faXNfaW50ZXJuYXRpb25hbCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnB1dF9lbGVtZW50ID0gJGlucHV0WzBdO1xuICAgICAgICAgICAgY29uc3QgY3Vyc29yX3BvcyA9IGlucHV0X2VsZW1lbnQuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZV9sZW5ndGggPSByYXcubGVuZ3RoO1xuXG4gICAgICAgICAgICAvLyBPbmx5IGFwcGx5IGxpdmUgZm9ybWF0dGluZyBpZiBjdXJzb3IgaXMgYXQgdGhlIGVuZFxuICAgICAgICAgICAgaWYgKGN1cnNvcl9wb3MgPT09IHZhbHVlX2xlbmd0aCkge1xuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBhbnkgbm9uLWRpZ2l0LCBub24tZm9ybWF0dGluZyBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgY29uc3QgY2xlYW5lZCA9IHJhdy5yZXBsYWNlKC9bXjAtOVxcc1xcLSgpXS9nLCAnJyk7XG4gICAgICAgICAgICAgICAgY29uc3QgZGlnaXRzID0gY2xlYW5lZC5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIGRpZ2l0cyB0byBmb3JtYXRcbiAgICAgICAgICAgICAgICBsZXQgZGlnaXRzX3RvX2Zvcm1hdDtcblxuICAgICAgICAgICAgICAgIGlmIChkaWdpdHMubGVuZ3RoID09PSAxMSAmJiBkaWdpdHMuY2hhckF0KDApID09PSAnMScgJiYgL1syLTldLy50ZXN0KGRpZ2l0cy5jaGFyQXQoMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEV4YWN0bHkgMTEgZGlnaXRzIHN0YXJ0aW5nIHdpdGggXCIxXCIgZm9sbG93ZWQgYnkgdmFsaWQgYXJlYSBjb2RlIGRpZ2l0ICgyLTkpXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBVUyBjb3VudHJ5IGNvZGUgLSBzdHJpcCB0aGUgbGVhZGluZyAxXG4gICAgICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHMuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlnaXRzLmxlbmd0aCA+IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1vcmUgdGhhbiAxMCBkaWdpdHMgLSBqdXN0IHRha2UgdGhlIGZpcnN0IDEwIGFuZCBpZ25vcmUgdGhlIHJlc3RcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzX3RvX2Zvcm1hdCA9IGRpZ2l0cy5zdWJzdHIoMCwgMTApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIDEwIG9yIGZld2VyIGRpZ2l0cyAtIHVzZSBhcy1pc1xuICAgICAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEZvcm1hdCB0aGUgZGlnaXRzXG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gdGhpcy5fZm9ybWF0X3VzX3Bob25lKGRpZ2l0c190b19mb3JtYXQpO1xuICAgICAgICAgICAgICAgICRpbnB1dC52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ3Vyc29yIGlzIG5vdCBhdCBlbmQgLSB1c2VyIGlzIGVkaXRpbmcgaW4gdGhlIG1pZGRsZVxuICAgICAgICAgICAgICAgIC8vIERvbid0IGZvcm1hdCwganVzdCBjbGVhbiBpbnZhbGlkIGNoYXJhY3RlcnNcbiAgICAgICAgICAgICAgICBjb25zdCBjbGVhbmVkID0gcmF3LnJlcGxhY2UoL1teMC05XFxzXFwtKCldL2csICcnKTtcbiAgICAgICAgICAgICAgICBpZiAoY2xlYW5lZCAhPT0gcmF3KSB7XG4gICAgICAgICAgICAgICAgICAgICRpbnB1dC52YWwoY2xlYW5lZCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc3RvcmUgY3Vyc29yIHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGlucHV0X2VsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UoY3Vyc29yX3BvcywgY3Vyc29yX3Bvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgYmx1ciB0byByZWZvcm1hdCB3aGVuIGRvbmUgZWRpdGluZ1xuICAgICAgICAkaW5wdXQub24oJ2JsdXInLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByYXcgPSAkaW5wdXQudmFsKCk7XG5cbiAgICAgICAgICAgIC8vIFNraXAgaWYgaW50ZXJuYXRpb25hbCBtb2RlIG9yIGVtcHR5XG4gICAgICAgICAgICBpZiAodGhpcy5fY2hlY2tfaW50ZXJuYXRpb25hbF9tb2RlKHJhdykgfHwgIXJhdykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmVmb3JtYXQgdGhlIGVudGlyZSB2YWx1ZSBvbiBibHVyXG4gICAgICAgICAgICBjb25zdCBkaWdpdHMgPSByYXcucmVwbGFjZSgvW14wLTldL2csICcnKTtcblxuICAgICAgICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIGRpZ2l0cyB0byBmb3JtYXRcbiAgICAgICAgICAgIGxldCBkaWdpdHNfdG9fZm9ybWF0O1xuXG4gICAgICAgICAgICBpZiAoZGlnaXRzLmxlbmd0aCA9PT0gMTEgJiYgZGlnaXRzLmNoYXJBdCgwKSA9PT0gJzEnICYmIC9bMi05XS8udGVzdChkaWdpdHMuY2hhckF0KDEpKSkge1xuICAgICAgICAgICAgICAgIC8vIEV4YWN0bHkgMTEgZGlnaXRzIHN0YXJ0aW5nIHdpdGggXCIxXCIgZm9sbG93ZWQgYnkgdmFsaWQgYXJlYSBjb2RlIGRpZ2l0ICgyLTkpXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIFVTIGNvdW50cnkgY29kZSAtIHN0cmlwIHRoZSBsZWFkaW5nIDFcbiAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGlnaXRzLmxlbmd0aCA+IDEwKSB7XG4gICAgICAgICAgICAgICAgLy8gTW9yZSB0aGFuIDEwIGRpZ2l0cyAtIGp1c3QgdGFrZSB0aGUgZmlyc3QgMTBcbiAgICAgICAgICAgICAgICBkaWdpdHNfdG9fZm9ybWF0ID0gZGlnaXRzLnN1YnN0cigwLCAxMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIDEwIG9yIGZld2VyIGRpZ2l0cyAtIHVzZSBhcy1pc1xuICAgICAgICAgICAgICAgIGRpZ2l0c190b19mb3JtYXQgPSBkaWdpdHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdHRlZCA9IHRoaXMuX2Zvcm1hdF91c19waG9uZShkaWdpdHNfdG9fZm9ybWF0KTtcbiAgICAgICAgICAgICRpbnB1dC52YWwoZm9ybWF0dGVkKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBmb3JtYXR0aW5nIGlmIHRoZXJlJ3MgYSB2YWx1ZVxuICAgICAgICBjb25zdCBpbml0aWFsX3ZhbHVlID0gJGlucHV0LnZhbCgpO1xuICAgICAgICBpZiAoaW5pdGlhbF92YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy52YWwoaW5pdGlhbF92YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQSxnQkFBZ0IsU0FBU0MsVUFBVSxDQUFDO0VBQ3RDQyxTQUFTQSxDQUFBLEVBQUc7SUFDUixLQUFLLENBQUNBLFNBQVMsQ0FBQyxDQUFDO0lBQ2pCLElBQUksQ0FBQ0MsaUJBQWlCLEdBQUcsS0FBSztFQUNsQzs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0VBQ0lDLHlCQUF5QkEsQ0FBQ0MsS0FBSyxFQUFFO0lBQzdCLE9BQU9BLEtBQUssSUFBSUMsR0FBRyxDQUFDRCxLQUFLLENBQUMsQ0FBQ0UsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUc7RUFDaEQ7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
|