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>
233 lines
30 KiB
JavaScript
Executable File
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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
|