Files
rspade_system/storage-working/rsx-tmp/babel_cache/f1174ef598a9a5010ed6bf2dced1269b_modern.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

233 lines
30 KiB
JavaScript
Executable File

"use strict";
// @JS-THIS-01-EXCEPTION
/**
* jQuery helper extensions for the RSX framework
* These extensions add utility methods to jQuery's prototype
* Note: 'this' references in jQuery extensions refer to jQuery objects by design
*/
class Rsx_Jq_Helpers {
/**
* Initialize jQuery extensions when the framework core is defined
* This method is called during framework initialization
*/
static _on_framework_core_define() {
// Returns true if jquery selector matched an element
$.fn.exists = function () {
return this.length > 0;
};
// Returns true if jquery element is visible
$.fn.is_visible = function () {
return this.is(':visible');
};
// Scrolls to the target element, only scrolls up. Todo: Create a version
// of this that also scrolls only down, or both
$.fn.scroll_up_to = function () {
let speed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
if (!this.exists()) {
// console.warn("Could not find target element to scroll to");
return;
}
if (!this.is_in_dom()) {
// console.warn("Target element for scroll is not on dom");
return;
}
let e_top = Math.round(this.offset().top);
let s_top = $('body').scrollTop();
if (e_top < 0) {
let target = s_top + e_top;
$('html, body').animate({
scrollTop: target
}, speed);
}
};
// $().is(":focus") - check if element has focus
$.expr[':'].focus = function (elem) {
return elem === document.activeElement && (elem.type || elem.href);
};
// Save native click behavior before override
$.fn._click_native = $.fn.click;
// Override .click() to call preventDefault by default
// This prevents accidental page navigation/form submission - the correct behavior 95% of the time
$.fn.click = function (handler) {
// If no handler provided, trigger click event (jQuery .click() with no args)
if (typeof handler === 'undefined') {
return this._click_native();
}
// Attach click handler with automatic preventDefault
return this.on('click', function (e) {
// Save original preventDefault
const original_preventDefault = e.preventDefault.bind(e);
// Override preventDefault to show warning when called explicitly
e.preventDefault = function () {
console.warn('event.preventDefault() is called automatically by RSpade .click() handlers and can be removed.');
return original_preventDefault();
};
// Call preventDefault before handler
original_preventDefault();
return handler.call(this, e);
});
};
// Escape hatch: click handler without preventDefault for the 5% case
$.fn.click_allow_default = function (handler) {
if (typeof handler === 'undefined') {
return this._click_native();
}
return this._click_native(handler);
};
// Returns true if the jquery element exists in and is attached to the DOM
$.fn.is_in_dom = function () {
let $element = this;
let _ancestor = function (HTMLobj) {
while (HTMLobj.parentElement) {
HTMLobj = HTMLobj.parentElement;
}
return HTMLobj;
};
return _ancestor($element[0]) === document.documentElement;
};
// Returns true if the element is visible in the viewport
$.fn.is_in_viewport = function () {
let scrolltop = $(window).scrollTop() > 0 ? $(window).scrollTop() : $('body').scrollTop();
let $element = this;
const top_of_element = $element.offset().top;
const bottom_of_element = $element.offset().top + $element.outerHeight();
const bottom_of_screen = scrolltop + $(window).innerHeight();
const top_of_screen = scrolltop;
if (bottom_of_screen > top_of_element && top_of_screen < bottom_of_element) {
return true;
} else {
return false;
}
};
// Gets the tagname of a jquery element
$.fn.tagname = function () {
return this.prop('tagName').toLowerCase();
};
// Returns true if a href is not same domain
$.fn.is_external = function () {
const host = window.location.host;
const link = $('<a>', {
href: this.attr('href')
})[0].hostname;
return link !== host;
};
// HTML5 form validation wrappers
$.fn.checkValidity = function () {
if (this.length === 0) return false;
return this[0].checkValidity();
};
$.fn.reportValidity = function () {
if (this.length === 0) return false;
return this[0].reportValidity();
};
$.fn.requestSubmit = function () {
if (this.length === 0) return this;
this[0].requestSubmit();
return this;
};
// Find related components by searching up the ancestor tree
// Like .closest() but searches within ancestors instead of matching them
$.fn.closest_sibling = function (selector) {
let $current = this;
let $parent = $current.parent();
// Keep going up the tree until we hit body
while ($parent.length > 0 && !$parent.is('body')) {
// Search within this parent for the selector
let $found = $parent.find(selector);
if ($found.length > 0) {
return $found;
}
// Move up one level
$parent = $parent.parent();
}
// If we reached body, search within body as well
if ($parent.is('body')) {
let $found = $parent.find(selector);
if ($found.length > 0) {
return $found;
}
}
// Return empty jQuery object if nothing found
return $();
};
// Override $.ajax to prevent direct AJAX calls to local server
// Developers must use the Ajax endpoint pattern: await Controller.method(params)
const native_ajax = $.ajax;
$.ajax = function (url, options) {
// Handle both $.ajax(url, options) and $.ajax(options) signatures
let settings;
if (typeof url === 'string') {
settings = options || {};
settings.url = url;
} else {
settings = url || {};
}
// Check if this is a local request (relative URL or same domain)
const request_url = settings.url || '';
const is_relative = !request_url.match(/^https?:\/\//);
const is_same_domain = request_url.startsWith(window.location.origin);
const is_local_request = is_relative || is_same_domain;
// Allow framework Ajax.call() to function
if (settings.__local_integration === true) {
return native_ajax.call(this, settings);
}
// Allow file upload endpoint - requires native $.ajax for FormData support
const is_file_upload = request_url === '/_upload' || request_url.endsWith('/_upload');
if (is_file_upload) {
return native_ajax.call(this, settings);
}
// Block local AJAX requests that don't use the Ajax endpoint pattern
if (is_local_request) {
// Try to parse controller and action from URL
let controller_name = null;
let action_name = null;
const url_match = request_url.match(/\/_rsx_api\/([^\/]+)\/([^\/\?]+)/);
if (url_match) {
controller_name = url_match[1];
action_name = url_match[2];
}
let error_message = 'AJAX requests to localhost via $.ajax() are prohibited.\n\n';
if (controller_name && action_name) {
error_message += `Instead of:\n`;
error_message += ` $.ajax({url: '${request_url}', ...})\n\n`;
error_message += `Use:\n`;
error_message += ` await ${controller_name}.${action_name}(parameters)\n\n`;
} else {
error_message += `Use the Ajax endpoint pattern:\n`;
error_message += ` await Controller_Name.action_name(parameters)\n\n`;
}
error_message += `The controller method must have the #[Ajax_Endpoint] attribute.`;
shouldnt_happen(error_message);
}
// Allow external requests (different domain)
return native_ajax.call(this, settings);
};
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSc3hfSnFfSGVscGVycyIsIl9vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUiLCIkIiwiZm4iLCJleGlzdHMiLCJsZW5ndGgiLCJpc192aXNpYmxlIiwiaXMiLCJzY3JvbGxfdXBfdG8iLCJzcGVlZCIsImFyZ3VtZW50cyIsInVuZGVmaW5lZCIsImlzX2luX2RvbSIsImVfdG9wIiwiTWF0aCIsInJvdW5kIiwib2Zmc2V0IiwidG9wIiwic190b3AiLCJzY3JvbGxUb3AiLCJ0YXJnZXQiLCJhbmltYXRlIiwiZXhwciIsImZvY3VzIiwiZWxlbSIsImRvY3VtZW50IiwiYWN0aXZlRWxlbWVudCIsInR5cGUiLCJocmVmIiwiX2NsaWNrX25hdGl2ZSIsImNsaWNrIiwiaGFuZGxlciIsIm9uIiwiZSIsIm9yaWdpbmFsX3ByZXZlbnREZWZhdWx0IiwicHJldmVudERlZmF1bHQiLCJiaW5kIiwiY29uc29sZSIsIndhcm4iLCJjYWxsIiwiY2xpY2tfYWxsb3dfZGVmYXVsdCIsIiRlbGVtZW50IiwiX2FuY2VzdG9yIiwiSFRNTG9iaiIsInBhcmVudEVsZW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiLCJpc19pbl92aWV3cG9ydCIsInNjcm9sbHRvcCIsIndpbmRvdyIsInRvcF9vZl9lbGVtZW50IiwiYm90dG9tX29mX2VsZW1lbnQiLCJvdXRlckhlaWdodCIsImJvdHRvbV9vZl9zY3JlZW4iLCJpbm5lckhlaWdodCIsInRvcF9vZl9zY3JlZW4iLCJ0YWduYW1lIiwicHJvcCIsInRvTG93ZXJDYXNlIiwiaXNfZXh0ZXJuYWwiLCJob3N0IiwibG9jYXRpb24iLCJsaW5rIiwiYXR0ciIsImhvc3RuYW1lIiwiY2hlY2tWYWxpZGl0eSIsInJlcG9ydFZhbGlkaXR5IiwicmVxdWVzdFN1Ym1pdCIsImNsb3Nlc3Rfc2libGluZyIsInNlbGVjdG9yIiwiJGN1cnJlbnQiLCIkcGFyZW50IiwicGFyZW50IiwiJGZvdW5kIiwiZmluZCIsIm5hdGl2ZV9hamF4IiwiYWpheCIsInVybCIsIm9wdGlvbnMiLCJzZXR0aW5ncyIsInJlcXVlc3RfdXJsIiwiaXNfcmVsYXRpdmUiLCJtYXRjaCIsImlzX3NhbWVfZG9tYWluIiwic3RhcnRzV2l0aCIsIm9yaWdpbiIsImlzX2xvY2FsX3JlcXVlc3QiLCJfX2xvY2FsX2ludGVncmF0aW9uIiwiaXNfZmlsZV91cGxvYWQiLCJlbmRzV2l0aCIsImNvbnRyb2xsZXJfbmFtZSIsImFjdGlvbl9uYW1lIiwidXJsX21hdGNoIiwiZXJyb3JfbWVzc2FnZSIsInNob3VsZG50X2hhcHBlbiJdLCJzb3VyY2VzIjpbImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSnFfSGVscGVycy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBASlMtVEhJUy0wMS1FWENFUFRJT05cbi8qKlxuICogalF1ZXJ5IGhlbHBlciBleHRlbnNpb25zIGZvciB0aGUgUlNYIGZyYW1ld29ya1xuICogVGhlc2UgZXh0ZW5zaW9ucyBhZGQgdXRpbGl0eSBtZXRob2RzIHRvIGpRdWVyeSdzIHByb3RvdHlwZVxuICogTm90ZTogJ3RoaXMnIHJlZmVyZW5jZXMgaW4galF1ZXJ5IGV4dGVuc2lvbnMgcmVmZXIgdG8galF1ZXJ5IG9iamVjdHMgYnkgZGVzaWduXG4gKi9cbmNsYXNzIFJzeF9KcV9IZWxwZXJzIHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGpRdWVyeSBleHRlbnNpb25zIHdoZW4gdGhlIGZyYW1ld29yayBjb3JlIGlzIGRlZmluZWRcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZHVyaW5nIGZyYW1ld29yayBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfZGVmaW5lKCkge1xuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYganF1ZXJ5IHNlbGVjdG9yIG1hdGNoZWQgYW4gZWxlbWVudFxuICAgICAgICAkLmZuLmV4aXN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxlbmd0aCA+IDA7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIGpxdWVyeSBlbGVtZW50IGlzIHZpc2libGVcbiAgICAgICAgJC5mbi5pc192aXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXMoJzp2aXNpYmxlJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2Nyb2xscyB0byB0aGUgdGFyZ2V0IGVsZW1lbnQsIG9ubHkgc2Nyb2xscyB1cC4gIFRvZG86IENyZWF0ZSBhIHZlcnNpb25cbiAgICAgICAgLy8gb2YgdGhpcyB0aGF0IGFsc28gc2Nyb2xscyBvbmx5IGRvd24sIG9yIGJvdGhcbiAgICAgICAgJC5mbi5zY3JvbGxfdXBfdG8gPSBmdW5jdGlvbiAoc3BlZWQgPSAwKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLndhcm4oXCJDb3VsZCBub3QgZmluZCB0YXJnZXQgZWxlbWVudCB0byBzY3JvbGwgdG9cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNfaW5fZG9tKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLndhcm4oXCJUYXJnZXQgZWxlbWVudCBmb3Igc2Nyb2xsIGlzIG5vdCBvbiBkb21cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgZV90b3AgPSBNYXRoLnJvdW5kKHRoaXMub2Zmc2V0KCkudG9wKTtcbiAgICAgICAgICAgIGxldCBzX3RvcCA9ICQoJ2JvZHknKS5zY3JvbGxUb3AoKTtcbiAgICAgICAgICAgIGlmIChlX3RvcCA8IDApIHtcbiAgICAgICAgICAgICAgICBsZXQgdGFyZ2V0ID0gc190b3AgKyBlX3RvcDtcbiAgICAgICAgICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZShcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsVG9wOiB0YXJnZXQsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHNwZWVkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyAkKCkuaXMoXCI6Zm9jdXNcIikgLSBjaGVjayBpZiBlbGVtZW50IGhhcyBmb2N1c1xuICAgICAgICAkLmV4cHJbJzonXS5mb2N1cyA9IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbSA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiAoZWxlbS50eXBlIHx8IGVsZW0uaHJlZik7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2F2ZSBuYXRpdmUgY2xpY2sgYmVoYXZpb3IgYmVmb3JlIG92ZXJyaWRlXG4gICAgICAgICQuZm4uX2NsaWNrX25hdGl2ZSA9ICQuZm4uY2xpY2s7XG5cbiAgICAgICAgLy8gT3ZlcnJpZGUgLmNsaWNrKCkgdG8gY2FsbCBwcmV2ZW50RGVmYXVsdCBieSBkZWZhdWx0XG4gICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWNjaWRlbnRhbCBwYWdlIG5hdmlnYXRpb24vZm9ybSBzdWJtaXNzaW9uIC0gdGhlIGNvcnJlY3QgYmVoYXZpb3IgOTUlIG9mIHRoZSB0aW1lXG4gICAgICAgICQuZm4uY2xpY2sgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICAgICAgLy8gSWYgbm8gaGFuZGxlciBwcm92aWRlZCwgdHJpZ2dlciBjbGljayBldmVudCAoalF1ZXJ5IC5jbGljaygpIHdpdGggbm8gYXJncylcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY2xpY2tfbmF0aXZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBjbGljayBoYW5kbGVyIHdpdGggYXV0b21hdGljIHByZXZlbnREZWZhdWx0XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIC8vIFNhdmUgb3JpZ2luYWwgcHJldmVudERlZmF1bHRcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCA9IGUucHJldmVudERlZmF1bHQuYmluZChlKTtcblxuICAgICAgICAgICAgICAgIC8vIE92ZXJyaWRlIHByZXZlbnREZWZhdWx0IHRvIHNob3cgd2FybmluZyB3aGVuIGNhbGxlZCBleHBsaWNpdGx5XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2V2ZW50LnByZXZlbnREZWZhdWx0KCkgaXMgY2FsbGVkIGF1dG9tYXRpY2FsbHkgYnkgUlNwYWRlIC5jbGljaygpIGhhbmRsZXJzIGFuZCBjYW4gYmUgcmVtb3ZlZC4nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX3ByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vIENhbGwgcHJldmVudERlZmF1bHQgYmVmb3JlIGhhbmRsZXJcbiAgICAgICAgICAgICAgICBvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIuY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEVzY2FwZSBoYXRjaDogY2xpY2sgaGFuZGxlciB3aXRob3V0IHByZXZlbnREZWZhdWx0IGZvciB0aGUgNSUgY2FzZVxuICAgICAgICAkLmZuLmNsaWNrX2FsbG93X2RlZmF1bHQgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbGlja19uYXRpdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbGlja19uYXRpdmUoaGFuZGxlcik7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoZSBqcXVlcnkgZWxlbWVudCBleGlzdHMgaW4gYW5kIGlzIGF0dGFjaGVkIHRvIHRoZSBET01cbiAgICAgICAgJC5mbi5pc19pbl9kb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsZXQgJGVsZW1lbnQgPSB0aGlzO1xuICAgICAgICAgICAgbGV0IF9hbmNlc3RvciA9IGZ1bmN0aW9uIChIVE1Mb2JqKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKEhUTUxvYmoucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBIVE1Mb2JqID0gSFRNTG9iai5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gSFRNTG9iajtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gX2FuY2VzdG9yKCRlbGVtZW50WzBdKSA9PT0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGUgZWxlbWVudCBpcyB2aXNpYmxlIGluIHRoZSB2aWV3cG9ydFxuICAgICAgICAkLmZuLmlzX2luX3ZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbGV0IHNjcm9sbHRvcCA9ICQod2luZG93KS5zY3JvbGxUb3AoKSA+IDAgPyAkKHdpbmRvdykuc2Nyb2xsVG9wKCkgOiAkKCdib2R5Jykuc2Nyb2xsVG9wKCk7XG5cbiAgICAgICAgICAgIGxldCAkZWxlbWVudCA9IHRoaXM7XG5cbiAgICAgICAgICAgIGNvbnN0IHRvcF9vZl9lbGVtZW50ID0gJGVsZW1lbnQub2Zmc2V0KCkudG9wO1xuICAgICAgICAgICAgY29uc3QgYm90dG9tX29mX2VsZW1lbnQgPSAkZWxlbWVudC5vZmZzZXQoKS50b3AgKyAkZWxlbWVudC5vdXRlckhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgYm90dG9tX29mX3NjcmVlbiA9IHNjcm9sbHRvcCArICQod2luZG93KS5pbm5lckhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgdG9wX29mX3NjcmVlbiA9IHNjcm9sbHRvcDtcblxuICAgICAgICAgICAgaWYgKGJvdHRvbV9vZl9zY3JlZW4gPiB0b3Bfb2ZfZWxlbWVudCAmJiB0b3Bfb2Zfc2NyZWVuIDwgYm90dG9tX29mX2VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldHMgdGhlIHRhZ25hbWUgb2YgYSBqcXVlcnkgZWxlbWVudFxuICAgICAgICAkLmZuLnRhZ25hbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9wKCd0YWdOYW1lJykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgYSBocmVmIGlzIG5vdCBzYW1lIGRvbWFpblxuICAgICAgICAkLmZuLmlzX2V4dGVybmFsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgaG9zdCA9IHdpbmRvdy5sb2NhdGlvbi5ob3N0O1xuICAgICAgICAgICAgY29uc3QgbGluayA9ICQoJzxhPicsIHtcbiAgICAgICAgICAgICAgICBocmVmOiB0aGlzLmF0dHIoJ2hyZWYnKSxcbiAgICAgICAgICAgIH0pWzBdLmhvc3RuYW1lO1xuICAgICAgICAgICAgcmV0dXJuIGxpbmsgIT09IGhvc3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gSFRNTDUgZm9ybSB2YWxpZGF0aW9uIHdyYXBwZXJzXG4gICAgICAgICQuZm4uY2hlY2tWYWxpZGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbMF0uY2hlY2tWYWxpZGl0eSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgICQuZm4ucmVwb3J0VmFsaWRpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzWzBdLnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgJC5mbi5yZXF1ZXN0U3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIHRoaXNbMF0ucmVxdWVzdFN1Ym1pdCgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluZCByZWxhdGVkIGNvbXBvbmVudHMgYnkgc2VhcmNoaW5nIHVwIHRoZSBhbmNlc3RvciB0cmVlXG4gICAgICAgIC8vIExpa2UgLmNsb3Nlc3QoKSBidXQgc2VhcmNoZXMgd2l0aGluIGFuY2VzdG9ycyBpbnN0ZWFkIG9mIG1hdGNoaW5nIHRoZW1cbiAgICAgICAgJC5mbi5jbG9zZXN0X3NpYmxpbmcgPSBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIGxldCAkY3VycmVudCA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgJHBhcmVudCA9ICRjdXJyZW50LnBhcmVudCgpO1xuXG4gICAgICAgICAgICAvLyBLZWVwIGdvaW5nIHVwIHRoZSB0cmVlIHVudGlsIHdlIGhpdCBib2R5XG4gICAgICAgICAgICB3aGlsZSAoJHBhcmVudC5sZW5ndGggPiAwICYmICEkcGFyZW50LmlzKCdib2R5JykpIHtcbiAgICAgICAgICAgICAgICAvLyBTZWFyY2ggd2l0aGluIHRoaXMgcGFyZW50IGZvciB0aGUgc2VsZWN0b3JcbiAgICAgICAgICAgICAgICBsZXQgJGZvdW5kID0gJHBhcmVudC5maW5kKHNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICBpZiAoJGZvdW5kLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRmb3VuZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIG9uZSBsZXZlbFxuICAgICAgICAgICAgICAgICRwYXJlbnQgPSAkcGFyZW50LnBhcmVudCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB3ZSByZWFjaGVkIGJvZHksIHNlYXJjaCB3aXRoaW4gYm9keSBhcyB3ZWxsXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5pcygnYm9keScpKSB7XG4gICAgICAgICAgICAgICAgbGV0ICRmb3VuZCA9ICRwYXJlbnQuZmluZChzZWxlY3Rvcik7XG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkZm91bmQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZXR1cm4gZW1wdHkgalF1ZXJ5IG9iamVjdCBpZiBub3RoaW5nIGZvdW5kXG4gICAgICAgICAgICByZXR1cm4gJCgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIE92ZXJyaWRlICQuYWpheCB0byBwcmV2ZW50IGRpcmVjdCBBSkFYIGNhbGxzIHRvIGxvY2FsIHNlcnZlclxuICAgICAgICAvLyBEZXZlbG9wZXJzIG11c3QgdXNlIHRoZSBBamF4IGVuZHBvaW50IHBhdHRlcm46IGF3YWl0IENvbnRyb2xsZXIubWV0aG9kKHBhcmFtcylcbiAgICAgICAgY29uc3QgbmF0aXZlX2FqYXggPSAkLmFqYXg7XG4gICAgICAgICQuYWpheCA9IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBib3RoICQuYWpheCh1cmwsIG9wdGlvbnMpIGFuZCAkLmFqYXgob3B0aW9ucykgc2lnbmF0dXJlc1xuICAgICAgICAgICAgbGV0IHNldHRpbmdzO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLnVybCA9IHVybDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSB1cmwgfHwge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBsb2NhbCByZXF1ZXN0IChyZWxhdGl2ZSBVUkwgb3Igc2FtZSBkb21haW4pXG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0X3VybCA9IHNldHRpbmdzLnVybCB8fCAnJztcbiAgICAgICAgICAgIGNvbnN0IGlzX3JlbGF0aXZlID0gIXJlcXVlc3RfdXJsLm1hdGNoKC9eaHR0cHM/OlxcL1xcLy8pO1xuICAgICAgICAgICAgY29uc3QgaXNfc2FtZV9kb21haW4gPSByZXF1ZXN0X3VybC5zdGFydHNXaXRoKHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pO1xuICAgICAgICAgICAgY29uc3QgaXNfbG9jYWxfcmVxdWVzdCA9IGlzX3JlbGF0aXZlIHx8IGlzX3NhbWVfZG9tYWluO1xuXG4gICAgICAgICAgICAvLyBBbGxvdyBmcmFtZXdvcmsgQWpheC5jYWxsKCkgdG8gZnVuY3Rpb25cbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5fX2xvY2FsX2ludGVncmF0aW9uID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZV9hamF4LmNhbGwodGhpcywgc2V0dGluZ3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBbGxvdyBmaWxlIHVwbG9hZCBlbmRwb2ludCAtIHJlcXVpcmVzIG5hdGl2ZSAkLmFqYXggZm9yIEZvcm1EYXRhIHN1cHBvcnRcbiAgICAgICAgICAgIGNvbnN0IGlzX2ZpbGVfdXBsb2FkID0gcmVxdWVzdF91cmwgPT09ICcvX3VwbG9hZCcgfHwgcmVxdWVzdF91cmwuZW5kc1dpdGgoJy9fdXBsb2FkJyk7XG4gICAgICAgICAgICBpZiAoaXNfZmlsZV91cGxvYWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlX2FqYXguY2FsbCh0aGlzLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJsb2NrIGxvY2FsIEFKQVggcmVxdWVzdHMgdGhhdCBkb24ndCB1c2UgdGhlIEFqYXggZW5kcG9pbnQgcGF0dGVyblxuICAgICAgICAgICAgaWYgKGlzX2xvY2FsX3JlcXVlc3QpIHtcbiAgICAgICAgICAgICAgICAvLyBUcnkgdG8gcGFyc2UgY29udHJvbGxlciBhbmQgYWN0aW9uIGZyb20gVVJMXG4gICAgICAgICAgICAgICAgbGV0IGNvbnRyb2xsZXJfbmFtZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGV0IGFjdGlvbl9uYW1lID0gbnVsbDtcbiAgICAgICAgICAgICAgICBjb25zdCB1cmxfbWF0Y2ggPSByZXF1ZXN0X3VybC5tYXRjaCgvXFwvX3JzeF9hcGlcXC8oW15cXC9dKylcXC8oW15cXC9cXD9dKykvKTtcbiAgICAgICAgICAgICAgICBpZiAodXJsX21hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXJfbmFtZSA9IHVybF9tYXRjaFsxXTtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uX25hbWUgPSB1cmxfbWF0Y2hbMl07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGVycm9yX21lc3NhZ2UgPSAnQUpBWCByZXF1ZXN0cyB0byBsb2NhbGhvc3QgdmlhICQuYWpheCgpIGFyZSBwcm9oaWJpdGVkLlxcblxcbic7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29udHJvbGxlcl9uYW1lICYmIGFjdGlvbl9uYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYEluc3RlYWQgb2Y6XFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgICAkLmFqYXgoe3VybDogJyR7cmVxdWVzdF91cmx9JywgLi4ufSlcXG5cXG5gO1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBVc2U6XFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgICBhd2FpdCAke2NvbnRyb2xsZXJfbmFtZX0uJHthY3Rpb25fbmFtZX0ocGFyYW1ldGVycylcXG5cXG5gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYFVzZSB0aGUgQWpheCBlbmRwb2ludCBwYXR0ZXJuOlxcbmA7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYCAgYXdhaXQgQ29udHJvbGxlcl9OYW1lLmFjdGlvbl9uYW1lKHBhcmFtZXRlcnMpXFxuXFxuYDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBUaGUgY29udHJvbGxlciBtZXRob2QgbXVzdCBoYXZlIHRoZSAjW0FqYXhfRW5kcG9pbnRdIGF0dHJpYnV0ZS5gO1xuXG4gICAgICAgICAgICAgICAgc2hvdWxkbnRfaGFwcGVuKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBbGxvdyBleHRlcm5hbCByZXF1ZXN0cyAoZGlmZmVyZW50IGRvbWFpbilcbiAgICAgICAgICAgIHJldHVybiBuYXRpdmVfYWpheC5jYWxsKHRoaXMsIHNldHRpbmdzKTtcbiAg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