Files
rspade_system/storage-broken/rsx-tmp/babel_0c426d49d165026d81a3ffd42e88286d.js
root 77b4d10af8 Refactor filename naming system and apply convention-based renames
Standardize settings file naming and relocate documentation files
Fix code quality violations from rsx:check
Reorganize user_management directory into logical subdirectories
Move Quill Bundle to core and align with Tom Select pattern
Simplify Site Settings page to focus on core site information
Complete Phase 5: Multi-tenant authentication with login flow and site selection
Add route query parameter rule and synchronize filename validation logic
Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs
Implement filename convention rule and resolve VS Code auto-rename conflict
Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns
Implement RPC server architecture for JavaScript parsing
WIP: Add RPC server infrastructure for JS parsing (partial implementation)
Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation
Add JQHTML-CLASS-01 rule and fix redundant class names
Improve code quality rules and resolve violations
Remove legacy fatal error format in favor of unified 'fatal' error type
Filter internal keys from window.rsxapp output
Update button styling and comprehensive form/modal documentation
Add conditional fly-in animation for modals
Fix non-deterministic bundle compilation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 19:10:02 +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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