Convert rails-ujs to ES2015 modules

Building and linting are setup similar to other packages

Most of the changes are related to converting from sprockets requires to
ESM imports/export. However, there are a few notable changes as well:

- A few methods have been refactored to store the Rails object in a
  closure so that properties on it can be overriden by applications (as
  documented and tested). This also resulted in the "start" module
  getting inlined so that it can use the resulting functions.

- The logic for running Rails.start() automatically had to change
  because Rollup uses a slightly different module format than the
  previous coffeescript bundle. The Rollup bundle does not set
  window.Rails until the end up the bundle, so the condition had to be
  updated and window.Rails had to be set manually to ensure backwards
  compatability with scripts listening to the rails:attachBindings event
This commit is contained in:
Hartley McGuire 2022-07-07 02:50:11 -04:00
parent 66353fd929
commit 7d116c93cf
No known key found for this signature in database
GPG Key ID: E823FC1403858A82
25 changed files with 1678 additions and 684 deletions

20
actionview/.eslintrc Normal file
View File

@ -0,0 +1,20 @@
{
"extends": "eslint:recommended",
"rules": {
"semi": ["error", "never"],
"quotes": ["error", "double"],
"no-unused-vars": ["error", { "vars": "all", "args": "none" }]
},
"plugins": [
"import"
],
"env": {
"browser": true,
"es6": true,
"jquery": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
}
}

View File

@ -7,7 +7,7 @@ require "open3"
desc "Default Task"
task default: :test
task package: %w( assets:compile assets:verify )
task :package
# Run the unit tests
@ -105,52 +105,6 @@ namespace :ujs do
end
end
namespace :assets do
desc "Compile Action View assets"
task :compile do
require "blade"
require "sprockets"
require "sprockets/export"
Blade.build
end
desc "Verify compiled Action View assets"
task :verify do
file = "lib/assets/compiled/rails-ujs.js"
pathname = Pathname.new("#{__dir__}/#{file}")
print "[verify] #{file} exists "
if pathname.exist?
puts "[OK]"
else
$stderr.puts "[FAIL]"
fail
end
print "[verify] #{file} is a UMD module "
if /module\.exports.*define\.amd/m.match?(pathname.read)
puts "[OK]"
else
$stderr.puts "[FAIL]"
fail
end
print "[verify] #{__dir__} can be required as a module "
js = <<-JS
window = { Event: class {} }
class Element {}
require('#{__dir__}')
JS
_, stderr, status = Open3.capture3("node", "--print", js)
if status.success?
puts "[OK]"
else
$stderr.puts "[FAIL]\n#{stderr}"
fail
end
end
end
task :lines do
load File.expand_path("../tools/line_statistics", __dir__)
files = FileList["lib/**/*.rb"]

View File

@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.email = "david@loudthinking.com"
s.homepage = "https://rubyonrails.org"
s.files = Dir["CHANGELOG.md", "README.rdoc", "MIT-LICENSE", "lib/**/*"]
s.files = Dir["CHANGELOG.md", "README.rdoc", "MIT-LICENSE", "lib/**/*", "app/assets/javascripts/*.js"]
s.require_path = "lib"
s.requirements << "none"

View File

@ -0,0 +1,668 @@
/*
Unobtrusive JavaScript
https://github.com/rails/rails/blob/main/actionview/app/javascript
Released under the MIT license
*/
const linkClickSelector = "a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]";
const buttonClickSelector = {
selector: "button[data-remote]:not([form]), button[data-confirm]:not([form])",
exclude: "form button"
};
const inputChangeSelector = "select[data-remote], input[data-remote], textarea[data-remote]";
const formSubmitSelector = "form:not([data-turbo=true])";
const formInputClickSelector = "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])";
const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled";
const formEnableSelector = "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled";
const fileInputSelector = "input[name][type=file]:not([disabled])";
const linkDisableSelector = "a[data-disable-with], a[data-disable]";
const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]";
let nonce = null;
const loadCSPNonce = () => {
const metaTag = document.querySelector("meta[name=csp-nonce]");
return nonce = metaTag && metaTag.content;
};
const cspNonce = () => nonce || loadCSPNonce();
const m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector;
const matches = function(element, selector) {
if (selector.exclude) {
return m.call(element, selector.selector) && !m.call(element, selector.exclude);
} else {
return m.call(element, selector);
}
};
const EXPANDO = "_ujsData";
const getData = (element, key) => element[EXPANDO] ? element[EXPANDO][key] : undefined;
const setData = function(element, key, value) {
if (!element[EXPANDO]) {
element[EXPANDO] = {};
}
return element[EXPANDO][key] = value;
};
const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector));
const csrfToken = () => {
const meta = document.querySelector("meta[name=csrf-token]");
return meta && meta.content;
};
const csrfParam = () => {
const meta = document.querySelector("meta[name=csrf-param]");
return meta && meta.content;
};
const CSRFProtection = xhr => {
const token = csrfToken();
if (token) {
return xhr.setRequestHeader("X-CSRF-Token", token);
}
};
const refreshCSRFTokens = () => {
const token = csrfToken();
const param = csrfParam();
if (token && param) {
return $('form input[name="' + param + '"]').forEach((input => input.value = token));
}
};
const AcceptHeaders = {
"*": "*/*",
text: "text/plain",
html: "text/html",
xml: "application/xml, text/xml",
json: "application/json, text/javascript",
script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
};
const ajax = options => {
options = prepareOptions(options);
var xhr = createXHR(options, (function() {
const response = processResponse(xhr.response != null ? xhr.response : xhr.responseText, xhr.getResponseHeader("Content-Type"));
if (Math.floor(xhr.status / 100) === 2) {
if (typeof options.success === "function") {
options.success(response, xhr.statusText, xhr);
}
} else {
if (typeof options.error === "function") {
options.error(response, xhr.statusText, xhr);
}
}
return typeof options.complete === "function" ? options.complete(xhr, xhr.statusText) : undefined;
}));
if (options.beforeSend && !options.beforeSend(xhr, options)) {
return false;
}
if (xhr.readyState === XMLHttpRequest.OPENED) {
return xhr.send(options.data);
}
};
var prepareOptions = function(options) {
options.url = options.url || location.href;
options.type = options.type.toUpperCase();
if (options.type === "GET" && options.data) {
if (options.url.indexOf("?") < 0) {
options.url += "?" + options.data;
} else {
options.url += "&" + options.data;
}
}
if (!(options.dataType in AcceptHeaders)) {
options.dataType = "*";
}
options.accept = AcceptHeaders[options.dataType];
if (options.dataType !== "*") {
options.accept += ", */*; q=0.01";
}
return options;
};
var createXHR = function(options, done) {
const xhr = new XMLHttpRequest;
xhr.open(options.type, options.url, true);
xhr.setRequestHeader("Accept", options.accept);
if (typeof options.data === "string") {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
}
if (!options.crossDomain) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
CSRFProtection(xhr);
}
xhr.withCredentials = !!options.withCredentials;
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
return done(xhr);
}
};
return xhr;
};
var processResponse = function(response, type) {
if (typeof response === "string" && typeof type === "string") {
if (type.match(/\bjson\b/)) {
try {
response = JSON.parse(response);
} catch (error) {}
} else if (type.match(/\b(?:java|ecma)script\b/)) {
const script = document.createElement("script");
script.setAttribute("nonce", cspNonce());
script.text = response;
document.head.appendChild(script).parentNode.removeChild(script);
} else if (type.match(/\b(xml|html|svg)\b/)) {
const parser = new DOMParser;
type = type.replace(/;.+/, "");
try {
response = parser.parseFromString(response, type);
} catch (error1) {}
}
}
return response;
};
const href = element => element.href;
const isCrossDomain = function(url) {
const originAnchor = document.createElement("a");
originAnchor.href = location.href;
const urlAnchor = document.createElement("a");
try {
urlAnchor.href = url;
return !((!urlAnchor.protocol || urlAnchor.protocol === ":") && !urlAnchor.host || originAnchor.protocol + "//" + originAnchor.host === urlAnchor.protocol + "//" + urlAnchor.host);
} catch (e) {
return true;
}
};
let preventDefault;
let {CustomEvent: CustomEvent} = window;
if (typeof CustomEvent !== "function") {
CustomEvent = function(event, params) {
const evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
CustomEvent.prototype = window.Event.prototype;
({preventDefault: preventDefault} = CustomEvent.prototype);
CustomEvent.prototype.preventDefault = function() {
const result = preventDefault.call(this);
if (this.cancelable && !this.defaultPrevented) {
Object.defineProperty(this, "defaultPrevented", {
get() {
return true;
}
});
}
return result;
};
}
const fire = (obj, name, data) => {
const event = new CustomEvent(name, {
bubbles: true,
cancelable: true,
detail: data
});
obj.dispatchEvent(event);
return !event.defaultPrevented;
};
const stopEverything = e => {
fire(e.target, "ujs:everythingStopped");
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
};
const delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, (function(e) {
let {target: target} = e;
while (!!(target instanceof Element) && !matches(target, selector)) {
target = target.parentNode;
}
if (target instanceof Element && handler.call(target, e) === false) {
e.preventDefault();
e.stopPropagation();
}
}));
const toArray = e => Array.prototype.slice.call(e);
const serializeElement = (element, additionalParam) => {
let inputs = [ element ];
if (matches(element, "form")) {
inputs = toArray(element.elements);
}
const params = [];
inputs.forEach((function(input) {
if (!input.name || input.disabled) {
return;
}
if (matches(input, "fieldset[disabled] *")) {
return;
}
if (matches(input, "select")) {
toArray(input.options).forEach((function(option) {
if (option.selected) {
params.push({
name: input.name,
value: option.value
});
}
}));
} else if (input.checked || [ "radio", "checkbox", "submit" ].indexOf(input.type) === -1) {
params.push({
name: input.name,
value: input.value
});
}
}));
if (additionalParam) {
params.push(additionalParam);
}
return params.map((function(param) {
if (param.name) {
return `${encodeURIComponent(param.name)}=${encodeURIComponent(param.value)}`;
} else {
return param;
}
})).join("&");
};
const formElements = (form, selector) => {
if (matches(form, "form")) {
return toArray(form.elements).filter((el => matches(el, selector)));
} else {
return toArray(form.querySelectorAll(selector));
}
};
const handleConfirmWithRails = rails => function(e) {
if (!allowAction(this, rails)) {
stopEverything(e);
}
};
const confirm = (message, element) => window.confirm(message);
var allowAction = function(element, rails) {
let callback;
const message = element.getAttribute("data-confirm");
if (!message) {
return true;
}
let answer = false;
if (fire(element, "confirm")) {
try {
answer = rails.confirm(message, element);
} catch (error) {}
callback = fire(element, "confirm:complete", [ answer ]);
}
return answer && callback;
};
const handleDisabledElement = function(e) {
const element = this;
if (element.disabled) {
stopEverything(e);
}
};
const enableElement = e => {
let element;
if (e instanceof Event) {
if (isXhrRedirect(e)) {
return;
}
element = e.target;
} else {
element = e;
}
if (matches(element, linkDisableSelector)) {
return enableLinkElement(element);
} else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {
return enableFormElement(element);
} else if (matches(element, formSubmitSelector)) {
return enableFormElements(element);
}
};
const disableElement = e => {
const element = e instanceof Event ? e.target : e;
if (matches(element, linkDisableSelector)) {
return disableLinkElement(element);
} else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {
return disableFormElement(element);
} else if (matches(element, formSubmitSelector)) {
return disableFormElements(element);
}
};
var disableLinkElement = function(element) {
if (getData(element, "ujs:disabled")) {
return;
}
const replacement = element.getAttribute("data-disable-with");
if (replacement != null) {
setData(element, "ujs:enable-with", element.innerHTML);
element.innerHTML = replacement;
}
element.addEventListener("click", stopEverything);
return setData(element, "ujs:disabled", true);
};
var enableLinkElement = function(element) {
const originalText = getData(element, "ujs:enable-with");
if (originalText != null) {
element.innerHTML = originalText;
setData(element, "ujs:enable-with", null);
}
element.removeEventListener("click", stopEverything);
return setData(element, "ujs:disabled", null);
};
var disableFormElements = form => formElements(form, formDisableSelector).forEach(disableFormElement);
var disableFormElement = function(element) {
if (getData(element, "ujs:disabled")) {
return;
}
const replacement = element.getAttribute("data-disable-with");
if (replacement != null) {
if (matches(element, "button")) {
setData(element, "ujs:enable-with", element.innerHTML);
element.innerHTML = replacement;
} else {
setData(element, "ujs:enable-with", element.value);
element.value = replacement;
}
}
element.disabled = true;
return setData(element, "ujs:disabled", true);
};
var enableFormElements = form => formElements(form, formEnableSelector).forEach((element => enableFormElement(element)));
var enableFormElement = function(element) {
const originalText = getData(element, "ujs:enable-with");
if (originalText != null) {
if (matches(element, "button")) {
element.innerHTML = originalText;
} else {
element.value = originalText;
}
setData(element, "ujs:enable-with", null);
}
element.disabled = false;
return setData(element, "ujs:disabled", null);
};
var isXhrRedirect = function(event) {
const xhr = event.detail ? event.detail[0] : undefined;
return xhr && xhr.getResponseHeader("X-Xhr-Redirect");
};
const handleMethodWithRails = rails => function(e) {
const link = this;
const method = link.getAttribute("data-method");
if (!method) {
return;
}
const href = rails.href(link);
const csrfToken$1 = csrfToken();
const csrfParam$1 = csrfParam();
const form = document.createElement("form");
let formContent = `<input name='_method' value='${method}' type='hidden' />`;
if (csrfParam$1 && csrfToken$1 && !isCrossDomain(href)) {
formContent += `<input name='${csrfParam$1}' value='${csrfToken$1}' type='hidden' />`;
}
formContent += '<input type="submit" />';
form.method = "post";
form.action = href;
form.target = link.target;
form.innerHTML = formContent;
form.style.display = "none";
document.body.appendChild(form);
form.querySelector('[type="submit"]').click();
stopEverything(e);
};
const isRemote = function(element) {
const value = element.getAttribute("data-remote");
return value != null && value !== "false";
};
const handleRemoteWithRails = rails => function(e) {
let data, method, url;
const element = this;
if (!isRemote(element)) {
return true;
}
if (!fire(element, "ajax:before")) {
fire(element, "ajax:stopped");
return false;
}
const withCredentials = element.getAttribute("data-with-credentials");
const dataType = element.getAttribute("data-type") || "script";
if (matches(element, formSubmitSelector)) {
const button = getData(element, "ujs:submit-button");
method = getData(element, "ujs:submit-button-formmethod") || element.getAttribute("method") || "get";
url = getData(element, "ujs:submit-button-formaction") || element.getAttribute("action") || location.href;
if (method.toUpperCase() === "GET") {
url = url.replace(/\?.*$/, "");
}
if (element.enctype === "multipart/form-data") {
data = new FormData(element);
if (button != null) {
data.append(button.name, button.value);
}
} else {
data = serializeElement(element, button);
}
setData(element, "ujs:submit-button", null);
setData(element, "ujs:submit-button-formmethod", null);
setData(element, "ujs:submit-button-formaction", null);
} else if (matches(element, buttonClickSelector) || matches(element, inputChangeSelector)) {
method = element.getAttribute("data-method");
url = element.getAttribute("data-url");
data = serializeElement(element, element.getAttribute("data-params"));
} else {
method = element.getAttribute("data-method");
url = rails.href(element);
data = element.getAttribute("data-params");
}
ajax({
type: method || "GET",
url: url,
data: data,
dataType: dataType,
beforeSend(xhr, options) {
if (fire(element, "ajax:beforeSend", [ xhr, options ])) {
return fire(element, "ajax:send", [ xhr ]);
} else {
fire(element, "ajax:stopped");
return false;
}
},
success(...args) {
return fire(element, "ajax:success", args);
},
error(...args) {
return fire(element, "ajax:error", args);
},
complete(...args) {
return fire(element, "ajax:complete", args);
},
crossDomain: isCrossDomain(url),
withCredentials: withCredentials != null && withCredentials !== "false"
});
stopEverything(e);
};
const formSubmitButtonClick = function(e) {
const button = this;
const {form: form} = button;
if (!form) {
return;
}
if (button.name) {
setData(form, "ujs:submit-button", {
name: button.name,
value: button.value
});
}
setData(form, "ujs:formnovalidate-button", button.formNoValidate);
setData(form, "ujs:submit-button-formaction", button.getAttribute("formaction"));
return setData(form, "ujs:submit-button-formmethod", button.getAttribute("formmethod"));
};
const preventInsignificantClick = function(e) {
const link = this;
const method = (link.getAttribute("data-method") || "GET").toUpperCase();
const data = link.getAttribute("data-params");
const metaClick = e.metaKey || e.ctrlKey;
const insignificantMetaClick = metaClick && method === "GET" && !data;
const nonPrimaryMouseClick = e.button != null && e.button !== 0;
if (nonPrimaryMouseClick || insignificantMetaClick) {
e.stopImmediatePropagation();
}
};
const Rails = {
$: $,
ajax: ajax,
buttonClickSelector: buttonClickSelector,
buttonDisableSelector: buttonDisableSelector,
confirm: confirm,
cspNonce: cspNonce,
csrfToken: csrfToken,
csrfParam: csrfParam,
CSRFProtection: CSRFProtection,
delegate: delegate,
disableElement: disableElement,
enableElement: enableElement,
fileInputSelector: fileInputSelector,
fire: fire,
formElements: formElements,
formEnableSelector: formEnableSelector,
formDisableSelector: formDisableSelector,
formInputClickSelector: formInputClickSelector,
formSubmitButtonClick: formSubmitButtonClick,
formSubmitSelector: formSubmitSelector,
getData: getData,
handleDisabledElement: handleDisabledElement,
href: href,
inputChangeSelector: inputChangeSelector,
isCrossDomain: isCrossDomain,
linkClickSelector: linkClickSelector,
linkDisableSelector: linkDisableSelector,
loadCSPNonce: loadCSPNonce,
matches: matches,
preventInsignificantClick: preventInsignificantClick,
refreshCSRFTokens: refreshCSRFTokens,
serializeElement: serializeElement,
setData: setData,
stopEverything: stopEverything
};
const handleConfirm = handleConfirmWithRails(Rails);
Rails.handleConfirm = handleConfirm;
const handleMethod = handleMethodWithRails(Rails);
Rails.handleMethod = handleMethod;
const handleRemote = handleRemoteWithRails(Rails);
Rails.handleRemote = handleRemote;
const start = function() {
if (window._rails_loaded) {
throw new Error("rails-ujs has already been loaded!");
}
window.addEventListener("pageshow", (function() {
$(formEnableSelector).forEach((function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el);
}
}));
$(linkDisableSelector).forEach((function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el);
}
}));
}));
delegate(document, linkDisableSelector, "ajax:complete", enableElement);
delegate(document, linkDisableSelector, "ajax:stopped", enableElement);
delegate(document, buttonDisableSelector, "ajax:complete", enableElement);
delegate(document, buttonDisableSelector, "ajax:stopped", enableElement);
delegate(document, linkClickSelector, "click", preventInsignificantClick);
delegate(document, linkClickSelector, "click", handleDisabledElement);
delegate(document, linkClickSelector, "click", handleConfirm);
delegate(document, linkClickSelector, "click", disableElement);
delegate(document, linkClickSelector, "click", handleRemote);
delegate(document, linkClickSelector, "click", handleMethod);
delegate(document, buttonClickSelector, "click", preventInsignificantClick);
delegate(document, buttonClickSelector, "click", handleDisabledElement);
delegate(document, buttonClickSelector, "click", handleConfirm);
delegate(document, buttonClickSelector, "click", disableElement);
delegate(document, buttonClickSelector, "click", handleRemote);
delegate(document, inputChangeSelector, "change", handleDisabledElement);
delegate(document, inputChangeSelector, "change", handleConfirm);
delegate(document, inputChangeSelector, "change", handleRemote);
delegate(document, formSubmitSelector, "submit", handleDisabledElement);
delegate(document, formSubmitSelector, "submit", handleConfirm);
delegate(document, formSubmitSelector, "submit", handleRemote);
delegate(document, formSubmitSelector, "submit", (e => setTimeout((() => disableElement(e)), 13)));
delegate(document, formSubmitSelector, "ajax:send", disableElement);
delegate(document, formSubmitSelector, "ajax:complete", enableElement);
delegate(document, formInputClickSelector, "click", preventInsignificantClick);
delegate(document, formInputClickSelector, "click", handleDisabledElement);
delegate(document, formInputClickSelector, "click", handleConfirm);
delegate(document, formInputClickSelector, "click", formSubmitButtonClick);
document.addEventListener("DOMContentLoaded", refreshCSRFTokens);
document.addEventListener("DOMContentLoaded", loadCSPNonce);
return window._rails_loaded = true;
};
Rails.start = start;
if (typeof jQuery !== "undefined" && jQuery && jQuery.ajax) {
if (jQuery.rails) {
throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.");
}
jQuery.rails = Rails;
jQuery.ajaxPrefilter((function(options, originalOptions, xhr) {
if (!options.crossDomain) {
return CSRFProtection(xhr);
}
}));
}
if (typeof exports !== "object" && typeof module === "undefined") {
window.Rails = Rails;
if (fire(document, "rails:attachBindings")) {
start();
}
}
export default Rails;

View File

@ -0,0 +1,606 @@
/*
Unobtrusive JavaScript
https://github.com/rails/rails/blob/main/actionview/app/javascript
Released under the MIT license
*/
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
global.Rails = factory());
})(this, (function() {
"use strict";
const linkClickSelector = "a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]";
const buttonClickSelector = {
selector: "button[data-remote]:not([form]), button[data-confirm]:not([form])",
exclude: "form button"
};
const inputChangeSelector = "select[data-remote], input[data-remote], textarea[data-remote]";
const formSubmitSelector = "form:not([data-turbo=true])";
const formInputClickSelector = "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])";
const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled";
const formEnableSelector = "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled";
const fileInputSelector = "input[name][type=file]:not([disabled])";
const linkDisableSelector = "a[data-disable-with], a[data-disable]";
const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]";
let nonce = null;
const loadCSPNonce = () => {
const metaTag = document.querySelector("meta[name=csp-nonce]");
return nonce = metaTag && metaTag.content;
};
const cspNonce = () => nonce || loadCSPNonce();
const m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector;
const matches = function(element, selector) {
if (selector.exclude) {
return m.call(element, selector.selector) && !m.call(element, selector.exclude);
} else {
return m.call(element, selector);
}
};
const EXPANDO = "_ujsData";
const getData = (element, key) => element[EXPANDO] ? element[EXPANDO][key] : undefined;
const setData = function(element, key, value) {
if (!element[EXPANDO]) {
element[EXPANDO] = {};
}
return element[EXPANDO][key] = value;
};
const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector));
const csrfToken = () => {
const meta = document.querySelector("meta[name=csrf-token]");
return meta && meta.content;
};
const csrfParam = () => {
const meta = document.querySelector("meta[name=csrf-param]");
return meta && meta.content;
};
const CSRFProtection = xhr => {
const token = csrfToken();
if (token) {
return xhr.setRequestHeader("X-CSRF-Token", token);
}
};
const refreshCSRFTokens = () => {
const token = csrfToken();
const param = csrfParam();
if (token && param) {
return $('form input[name="' + param + '"]').forEach((input => input.value = token));
}
};
const AcceptHeaders = {
"*": "*/*",
text: "text/plain",
html: "text/html",
xml: "application/xml, text/xml",
json: "application/json, text/javascript",
script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
};
const ajax = options => {
options = prepareOptions(options);
var xhr = createXHR(options, (function() {
const response = processResponse(xhr.response != null ? xhr.response : xhr.responseText, xhr.getResponseHeader("Content-Type"));
if (Math.floor(xhr.status / 100) === 2) {
if (typeof options.success === "function") {
options.success(response, xhr.statusText, xhr);
}
} else {
if (typeof options.error === "function") {
options.error(response, xhr.statusText, xhr);
}
}
return typeof options.complete === "function" ? options.complete(xhr, xhr.statusText) : undefined;
}));
if (options.beforeSend && !options.beforeSend(xhr, options)) {
return false;
}
if (xhr.readyState === XMLHttpRequest.OPENED) {
return xhr.send(options.data);
}
};
var prepareOptions = function(options) {
options.url = options.url || location.href;
options.type = options.type.toUpperCase();
if (options.type === "GET" && options.data) {
if (options.url.indexOf("?") < 0) {
options.url += "?" + options.data;
} else {
options.url += "&" + options.data;
}
}
if (!(options.dataType in AcceptHeaders)) {
options.dataType = "*";
}
options.accept = AcceptHeaders[options.dataType];
if (options.dataType !== "*") {
options.accept += ", */*; q=0.01";
}
return options;
};
var createXHR = function(options, done) {
const xhr = new XMLHttpRequest;
xhr.open(options.type, options.url, true);
xhr.setRequestHeader("Accept", options.accept);
if (typeof options.data === "string") {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
}
if (!options.crossDomain) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
CSRFProtection(xhr);
}
xhr.withCredentials = !!options.withCredentials;
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
return done(xhr);
}
};
return xhr;
};
var processResponse = function(response, type) {
if (typeof response === "string" && typeof type === "string") {
if (type.match(/\bjson\b/)) {
try {
response = JSON.parse(response);
} catch (error) {}
} else if (type.match(/\b(?:java|ecma)script\b/)) {
const script = document.createElement("script");
script.setAttribute("nonce", cspNonce());
script.text = response;
document.head.appendChild(script).parentNode.removeChild(script);
} else if (type.match(/\b(xml|html|svg)\b/)) {
const parser = new DOMParser;
type = type.replace(/;.+/, "");
try {
response = parser.parseFromString(response, type);
} catch (error1) {}
}
}
return response;
};
const href = element => element.href;
const isCrossDomain = function(url) {
const originAnchor = document.createElement("a");
originAnchor.href = location.href;
const urlAnchor = document.createElement("a");
try {
urlAnchor.href = url;
return !((!urlAnchor.protocol || urlAnchor.protocol === ":") && !urlAnchor.host || originAnchor.protocol + "//" + originAnchor.host === urlAnchor.protocol + "//" + urlAnchor.host);
} catch (e) {
return true;
}
};
let preventDefault;
let {CustomEvent: CustomEvent} = window;
if (typeof CustomEvent !== "function") {
CustomEvent = function(event, params) {
const evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
CustomEvent.prototype = window.Event.prototype;
({preventDefault: preventDefault} = CustomEvent.prototype);
CustomEvent.prototype.preventDefault = function() {
const result = preventDefault.call(this);
if (this.cancelable && !this.defaultPrevented) {
Object.defineProperty(this, "defaultPrevented", {
get() {
return true;
}
});
}
return result;
};
}
const fire = (obj, name, data) => {
const event = new CustomEvent(name, {
bubbles: true,
cancelable: true,
detail: data
});
obj.dispatchEvent(event);
return !event.defaultPrevented;
};
const stopEverything = e => {
fire(e.target, "ujs:everythingStopped");
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
};
const delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, (function(e) {
let {target: target} = e;
while (!!(target instanceof Element) && !matches(target, selector)) {
target = target.parentNode;
}
if (target instanceof Element && handler.call(target, e) === false) {
e.preventDefault();
e.stopPropagation();
}
}));
const toArray = e => Array.prototype.slice.call(e);
const serializeElement = (element, additionalParam) => {
let inputs = [ element ];
if (matches(element, "form")) {
inputs = toArray(element.elements);
}
const params = [];
inputs.forEach((function(input) {
if (!input.name || input.disabled) {
return;
}
if (matches(input, "fieldset[disabled] *")) {
return;
}
if (matches(input, "select")) {
toArray(input.options).forEach((function(option) {
if (option.selected) {
params.push({
name: input.name,
value: option.value
});
}
}));
} else if (input.checked || [ "radio", "checkbox", "submit" ].indexOf(input.type) === -1) {
params.push({
name: input.name,
value: input.value
});
}
}));
if (additionalParam) {
params.push(additionalParam);
}
return params.map((function(param) {
if (param.name) {
return `${encodeURIComponent(param.name)}=${encodeURIComponent(param.value)}`;
} else {
return param;
}
})).join("&");
};
const formElements = (form, selector) => {
if (matches(form, "form")) {
return toArray(form.elements).filter((el => matches(el, selector)));
} else {
return toArray(form.querySelectorAll(selector));
}
};
const handleConfirmWithRails = rails => function(e) {
if (!allowAction(this, rails)) {
stopEverything(e);
}
};
const confirm = (message, element) => window.confirm(message);
var allowAction = function(element, rails) {
let callback;
const message = element.getAttribute("data-confirm");
if (!message) {
return true;
}
let answer = false;
if (fire(element, "confirm")) {
try {
answer = rails.confirm(message, element);
} catch (error) {}
callback = fire(element, "confirm:complete", [ answer ]);
}
return answer && callback;
};
const handleDisabledElement = function(e) {
const element = this;
if (element.disabled) {
stopEverything(e);
}
};
const enableElement = e => {
let element;
if (e instanceof Event) {
if (isXhrRedirect(e)) {
return;
}
element = e.target;
} else {
element = e;
}
if (matches(element, linkDisableSelector)) {
return enableLinkElement(element);
} else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {
return enableFormElement(element);
} else if (matches(element, formSubmitSelector)) {
return enableFormElements(element);
}
};
const disableElement = e => {
const element = e instanceof Event ? e.target : e;
if (matches(element, linkDisableSelector)) {
return disableLinkElement(element);
} else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {
return disableFormElement(element);
} else if (matches(element, formSubmitSelector)) {
return disableFormElements(element);
}
};
var disableLinkElement = function(element) {
if (getData(element, "ujs:disabled")) {
return;
}
const replacement = element.getAttribute("data-disable-with");
if (replacement != null) {
setData(element, "ujs:enable-with", element.innerHTML);
element.innerHTML = replacement;
}
element.addEventListener("click", stopEverything);
return setData(element, "ujs:disabled", true);
};
var enableLinkElement = function(element) {
const originalText = getData(element, "ujs:enable-with");
if (originalText != null) {
element.innerHTML = originalText;
setData(element, "ujs:enable-with", null);
}
element.removeEventListener("click", stopEverything);
return setData(element, "ujs:disabled", null);
};
var disableFormElements = form => formElements(form, formDisableSelector).forEach(disableFormElement);
var disableFormElement = function(element) {
if (getData(element, "ujs:disabled")) {
return;
}
const replacement = element.getAttribute("data-disable-with");
if (replacement != null) {
if (matches(element, "button")) {
setData(element, "ujs:enable-with", element.innerHTML);
element.innerHTML = replacement;
} else {
setData(element, "ujs:enable-with", element.value);
element.value = replacement;
}
}
element.disabled = true;
return setData(element, "ujs:disabled", true);
};
var enableFormElements = form => formElements(form, formEnableSelector).forEach((element => enableFormElement(element)));
var enableFormElement = function(element) {
const originalText = getData(element, "ujs:enable-with");
if (originalText != null) {
if (matches(element, "button")) {
element.innerHTML = originalText;
} else {
element.value = originalText;
}
setData(element, "ujs:enable-with", null);
}
element.disabled = false;
return setData(element, "ujs:disabled", null);
};
var isXhrRedirect = function(event) {
const xhr = event.detail ? event.detail[0] : undefined;
return xhr && xhr.getResponseHeader("X-Xhr-Redirect");
};
const handleMethodWithRails = rails => function(e) {
const link = this;
const method = link.getAttribute("data-method");
if (!method) {
return;
}
const href = rails.href(link);
const csrfToken$1 = csrfToken();
const csrfParam$1 = csrfParam();
const form = document.createElement("form");
let formContent = `<input name='_method' value='${method}' type='hidden' />`;
if (csrfParam$1 && csrfToken$1 && !isCrossDomain(href)) {
formContent += `<input name='${csrfParam$1}' value='${csrfToken$1}' type='hidden' />`;
}
formContent += '<input type="submit" />';
form.method = "post";
form.action = href;
form.target = link.target;
form.innerHTML = formContent;
form.style.display = "none";
document.body.appendChild(form);
form.querySelector('[type="submit"]').click();
stopEverything(e);
};
const isRemote = function(element) {
const value = element.getAttribute("data-remote");
return value != null && value !== "false";
};
const handleRemoteWithRails = rails => function(e) {
let data, method, url;
const element = this;
if (!isRemote(element)) {
return true;
}
if (!fire(element, "ajax:before")) {
fire(element, "ajax:stopped");
return false;
}
const withCredentials = element.getAttribute("data-with-credentials");
const dataType = element.getAttribute("data-type") || "script";
if (matches(element, formSubmitSelector)) {
const button = getData(element, "ujs:submit-button");
method = getData(element, "ujs:submit-button-formmethod") || element.getAttribute("method") || "get";
url = getData(element, "ujs:submit-button-formaction") || element.getAttribute("action") || location.href;
if (method.toUpperCase() === "GET") {
url = url.replace(/\?.*$/, "");
}
if (element.enctype === "multipart/form-data") {
data = new FormData(element);
if (button != null) {
data.append(button.name, button.value);
}
} else {
data = serializeElement(element, button);
}
setData(element, "ujs:submit-button", null);
setData(element, "ujs:submit-button-formmethod", null);
setData(element, "ujs:submit-button-formaction", null);
} else if (matches(element, buttonClickSelector) || matches(element, inputChangeSelector)) {
method = element.getAttribute("data-method");
url = element.getAttribute("data-url");
data = serializeElement(element, element.getAttribute("data-params"));
} else {
method = element.getAttribute("data-method");
url = rails.href(element);
data = element.getAttribute("data-params");
}
ajax({
type: method || "GET",
url: url,
data: data,
dataType: dataType,
beforeSend(xhr, options) {
if (fire(element, "ajax:beforeSend", [ xhr, options ])) {
return fire(element, "ajax:send", [ xhr ]);
} else {
fire(element, "ajax:stopped");
return false;
}
},
success(...args) {
return fire(element, "ajax:success", args);
},
error(...args) {
return fire(element, "ajax:error", args);
},
complete(...args) {
return fire(element, "ajax:complete", args);
},
crossDomain: isCrossDomain(url),
withCredentials: withCredentials != null && withCredentials !== "false"
});
stopEverything(e);
};
const formSubmitButtonClick = function(e) {
const button = this;
const {form: form} = button;
if (!form) {
return;
}
if (button.name) {
setData(form, "ujs:submit-button", {
name: button.name,
value: button.value
});
}
setData(form, "ujs:formnovalidate-button", button.formNoValidate);
setData(form, "ujs:submit-button-formaction", button.getAttribute("formaction"));
return setData(form, "ujs:submit-button-formmethod", button.getAttribute("formmethod"));
};
const preventInsignificantClick = function(e) {
const link = this;
const method = (link.getAttribute("data-method") || "GET").toUpperCase();
const data = link.getAttribute("data-params");
const metaClick = e.metaKey || e.ctrlKey;
const insignificantMetaClick = metaClick && method === "GET" && !data;
const nonPrimaryMouseClick = e.button != null && e.button !== 0;
if (nonPrimaryMouseClick || insignificantMetaClick) {
e.stopImmediatePropagation();
}
};
const Rails = {
$: $,
ajax: ajax,
buttonClickSelector: buttonClickSelector,
buttonDisableSelector: buttonDisableSelector,
confirm: confirm,
cspNonce: cspNonce,
csrfToken: csrfToken,
csrfParam: csrfParam,
CSRFProtection: CSRFProtection,
delegate: delegate,
disableElement: disableElement,
enableElement: enableElement,
fileInputSelector: fileInputSelector,
fire: fire,
formElements: formElements,
formEnableSelector: formEnableSelector,
formDisableSelector: formDisableSelector,
formInputClickSelector: formInputClickSelector,
formSubmitButtonClick: formSubmitButtonClick,
formSubmitSelector: formSubmitSelector,
getData: getData,
handleDisabledElement: handleDisabledElement,
href: href,
inputChangeSelector: inputChangeSelector,
isCrossDomain: isCrossDomain,
linkClickSelector: linkClickSelector,
linkDisableSelector: linkDisableSelector,
loadCSPNonce: loadCSPNonce,
matches: matches,
preventInsignificantClick: preventInsignificantClick,
refreshCSRFTokens: refreshCSRFTokens,
serializeElement: serializeElement,
setData: setData,
stopEverything: stopEverything
};
const handleConfirm = handleConfirmWithRails(Rails);
Rails.handleConfirm = handleConfirm;
const handleMethod = handleMethodWithRails(Rails);
Rails.handleMethod = handleMethod;
const handleRemote = handleRemoteWithRails(Rails);
Rails.handleRemote = handleRemote;
const start = function() {
if (window._rails_loaded) {
throw new Error("rails-ujs has already been loaded!");
}
window.addEventListener("pageshow", (function() {
$(formEnableSelector).forEach((function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el);
}
}));
$(linkDisableSelector).forEach((function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el);
}
}));
}));
delegate(document, linkDisableSelector, "ajax:complete", enableElement);
delegate(document, linkDisableSelector, "ajax:stopped", enableElement);
delegate(document, buttonDisableSelector, "ajax:complete", enableElement);
delegate(document, buttonDisableSelector, "ajax:stopped", enableElement);
delegate(document, linkClickSelector, "click", preventInsignificantClick);
delegate(document, linkClickSelector, "click", handleDisabledElement);
delegate(document, linkClickSelector, "click", handleConfirm);
delegate(document, linkClickSelector, "click", disableElement);
delegate(document, linkClickSelector, "click", handleRemote);
delegate(document, linkClickSelector, "click", handleMethod);
delegate(document, buttonClickSelector, "click", preventInsignificantClick);
delegate(document, buttonClickSelector, "click", handleDisabledElement);
delegate(document, buttonClickSelector, "click", handleConfirm);
delegate(document, buttonClickSelector, "click", disableElement);
delegate(document, buttonClickSelector, "click", handleRemote);
delegate(document, inputChangeSelector, "change", handleDisabledElement);
delegate(document, inputChangeSelector, "change", handleConfirm);
delegate(document, inputChangeSelector, "change", handleRemote);
delegate(document, formSubmitSelector, "submit", handleDisabledElement);
delegate(document, formSubmitSelector, "submit", handleConfirm);
delegate(document, formSubmitSelector, "submit", handleRemote);
delegate(document, formSubmitSelector, "submit", (e => setTimeout((() => disableElement(e)), 13)));
delegate(document, formSubmitSelector, "ajax:send", disableElement);
delegate(document, formSubmitSelector, "ajax:complete", enableElement);
delegate(document, formInputClickSelector, "click", preventInsignificantClick);
delegate(document, formInputClickSelector, "click", handleDisabledElement);
delegate(document, formInputClickSelector, "click", handleConfirm);
delegate(document, formInputClickSelector, "click", formSubmitButtonClick);
document.addEventListener("DOMContentLoaded", refreshCSRFTokens);
document.addEventListener("DOMContentLoaded", loadCSPNonce);
return window._rails_loaded = true;
};
Rails.start = start;
if (typeof jQuery !== "undefined" && jQuery && jQuery.ajax) {
if (jQuery.rails) {
throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.");
}
jQuery.rails = Rails;
jQuery.ajaxPrefilter((function(options, originalOptions, xhr) {
if (!options.crossDomain) {
return CSRFProtection(xhr);
}
}));
}
if (typeof exports !== "object" && typeof module === "undefined") {
window.Rails = Rails;
if (fire(document, "rails:attachBindings")) {
start();
}
}
return Rails;
}));

View File

@ -1,41 +0,0 @@
//= require ./rails-ujs/BANNER
//= export Rails
//= require_self
//= require_tree ./rails-ujs/utils
//= require_tree ./rails-ujs/features
//= require ./rails-ujs/start
this.Rails = {
// Link elements bound by rails-ujs
linkClickSelector: "a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]",
// Button elements bound by rails-ujs
buttonClickSelector: {
selector: "button[data-remote]:not([form]), button[data-confirm]:not([form])",
exclude: "form button"
},
// Select elements bound by rails-ujs
inputChangeSelector: "select[data-remote], input[data-remote], textarea[data-remote]",
// Form elements bound by rails-ujs
formSubmitSelector: "form:not([data-turbo=true])",
// Form input elements bound by rails-ujs
formInputClickSelector: "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])",
// Form input elements disabled during form submission
formDisableSelector: "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled",
// Form input elements re-enabled after form submission
formEnableSelector: "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled",
// Form file input elements
fileInputSelector: "input[name][type=file]:not([disabled])",
// Link onClick disable selector with possible re-enable after remote submission
linkDisableSelector: "a[data-disable-with], a[data-disable]",
// Button onClick disable selector with possible re-enable after remote submission
buttonDisableSelector: "button[data-remote][data-disable-with], button[data-remote][data-disable]"
}

View File

@ -1,5 +0,0 @@
/*
Unobtrusive JavaScript
https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts
Released under the MIT license
*/

View File

@ -1,13 +1,11 @@
//= require_tree ../utils
import { fire, stopEverything } from "../utils/event"
const { fire, stopEverything } = Rails
Rails.handleConfirm = function(e) {
if (!allowAction(this)) { stopEverything(e) }
const handleConfirmWithRails = (rails) => function(e) {
if (!allowAction(this, rails)) { stopEverything(e) }
}
// Default confirm dialog, may be overridden with custom confirm dialog in Rails.confirm
Rails.confirm = (message, element) => confirm(message)
const confirm = (message, element) => window.confirm(message)
// For 'data-confirm' attribute:
// - Fires `confirm` event
@ -18,16 +16,18 @@ Rails.confirm = (message, element) => confirm(message)
// Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
// Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
// return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
var allowAction = function(element) {
var allowAction = function(element, rails) {
let callback
const message = element.getAttribute("data-confirm")
if (!message) { return true }
let answer = false
if (fire(element, "confirm")) {
try { answer = Rails.confirm(message, element) } catch (error) { /* do nothing */ }
try { answer = rails.confirm(message, element) } catch(error) { /* do nothing */ }
callback = fire(element, "confirm:complete", [answer])
}
return answer && callback
}
export { handleConfirmWithRails, confirm }

View File

@ -1,14 +1,21 @@
//= require_tree ../utils
import {
linkDisableSelector,
buttonDisableSelector,
formDisableSelector,
formEnableSelector,
formSubmitSelector
} from "../utils/constants"
import { matches, getData, setData } from "../utils/dom"
import { stopEverything } from "../utils/event"
import { formElements } from "../utils/form"
const { matches, getData, setData, stopEverything, formElements } = Rails
Rails.handleDisabledElement = function(e) {
const handleDisabledElement = function(e) {
const element = this
if (element.disabled) { stopEverything(e) }
}
// Unified function to enable an element (link, button and form)
Rails.enableElement = function(e) {
const enableElement = (e) => {
let element
if (e instanceof Event) {
if (isXhrRedirect(e)) { return }
@ -17,23 +24,23 @@ Rails.enableElement = function(e) {
element = e
}
if (matches(element, Rails.linkDisableSelector)) {
if (matches(element, linkDisableSelector)) {
return enableLinkElement(element)
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formEnableSelector)) {
} else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {
return enableFormElement(element)
} else if (matches(element, Rails.formSubmitSelector)) {
} else if (matches(element, formSubmitSelector)) {
return enableFormElements(element)
}
}
// Unified function to disable an element (link, button and form)
Rails.disableElement = function(e) {
const disableElement = (e) => {
const element = e instanceof Event ? e.target : e
if (matches(element, Rails.linkDisableSelector)) {
if (matches(element, linkDisableSelector)) {
return disableLinkElement(element)
} else if (matches(element, Rails.buttonDisableSelector) || matches(element, Rails.formDisableSelector)) {
} else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {
return disableFormElement(element)
} else if (matches(element, Rails.formSubmitSelector)) {
} else if (matches(element, formSubmitSelector)) {
return disableFormElements(element)
}
}
@ -66,7 +73,7 @@ var enableLinkElement = function(element) {
// - Caches element value in 'ujs:enable-with' data store
// - Replaces element text with value of 'data-disable-with' attribute
// - Sets disabled property to true
var disableFormElements = form => formElements(form, Rails.formDisableSelector).forEach(disableFormElement)
var disableFormElements = form => formElements(form, formDisableSelector).forEach(disableFormElement)
var disableFormElement = function(element) {
if (getData(element, "ujs:disabled")) { return }
@ -87,7 +94,7 @@ var disableFormElement = function(element) {
// Re-enables disabled form elements:
// - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
// - Sets disabled property to false
var enableFormElements = form => formElements(form, Rails.formEnableSelector).forEach(enableFormElement)
var enableFormElements = form => formElements(form, formEnableSelector).forEach(element => enableFormElement(element))
var enableFormElement = function(element) {
const originalText = getData(element, "ujs:enable-with")
@ -107,3 +114,5 @@ var isXhrRedirect = function(event) {
const xhr = event.detail ? event.detail[0] : undefined
return xhr && xhr.getResponseHeader("X-Xhr-Redirect")
}
export { handleDisabledElement, enableElement, disableElement }

View File

@ -1,21 +1,21 @@
//= require_tree ../utils
const { stopEverything } = Rails
import { isCrossDomain } from "../utils/ajax"
import * as csrf from "../utils/csrf"
import { stopEverything } from "../utils/event"
// Handles "data-method" on links such as:
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
Rails.handleMethod = function(e) {
const handleMethodWithRails = (rails) => function(e) {
const link = this
const method = link.getAttribute("data-method")
if (!method) { return }
const href = Rails.href(link)
const csrfToken = Rails.csrfToken()
const csrfParam = Rails.csrfParam()
const href = rails.href(link)
const csrfToken = csrf.csrfToken()
const csrfParam = csrf.csrfParam()
const form = document.createElement("form")
let formContent = `<input name='_method' value='${method}' type='hidden' />`
if (csrfParam && csrfToken && !Rails.isCrossDomain(href)) {
if (csrfParam && csrfToken && !isCrossDomain(href)) {
formContent += `<input name='${csrfParam}' value='${csrfToken}' type='hidden' />`
}
@ -34,3 +34,5 @@ Rails.handleMethod = function(e) {
stopEverything(e)
}
export { handleMethodWithRails }

View File

@ -1,11 +1,8 @@
//= require_tree ../utils
const {
matches, getData, setData,
fire, stopEverything,
ajax, isCrossDomain,
serializeElement
} = Rails
import { formSubmitSelector, buttonClickSelector, inputChangeSelector } from "../utils/constants"
import { ajax, isCrossDomain } from "../utils/ajax"
import { matches, getData, setData } from "../utils/dom"
import { fire, stopEverything } from "../utils/event"
import { serializeElement } from "../utils/form"
// Checks "data-remote" if true to handle the request through a XHR request.
const isRemote = function(element) {
@ -14,7 +11,7 @@ const isRemote = function(element) {
}
// Submits "remote" forms and links with ajax
Rails.handleRemote = function(e) {
const handleRemoteWithRails = (rails) => function(e) {
let data, method, url
const element = this
@ -27,7 +24,7 @@ Rails.handleRemote = function(e) {
const withCredentials = element.getAttribute("data-with-credentials")
const dataType = element.getAttribute("data-type") || "script"
if (matches(element, Rails.formSubmitSelector)) {
if (matches(element, formSubmitSelector)) {
// memoized value from clicked submit button
const button = getData(element, "ujs:submit-button")
method = getData(element, "ujs:submit-button-formmethod") || element.getAttribute("method") || "get"
@ -46,13 +43,13 @@ Rails.handleRemote = function(e) {
setData(element, "ujs:submit-button", null)
setData(element, "ujs:submit-button-formmethod", null)
setData(element, "ujs:submit-button-formaction", null)
} else if (matches(element, Rails.buttonClickSelector) || matches(element, Rails.inputChangeSelector)) {
} else if (matches(element, buttonClickSelector) || matches(element, inputChangeSelector)) {
method = element.getAttribute("data-method")
url = element.getAttribute("data-url")
data = serializeElement(element, element.getAttribute("data-params"))
} else {
method = element.getAttribute("data-method")
url = Rails.href(element)
url = rails.href(element)
data = element.getAttribute("data-params")
}
@ -79,7 +76,7 @@ Rails.handleRemote = function(e) {
stopEverything(e)
}
Rails.formSubmitButtonClick = function(e) {
const formSubmitButtonClick = function(e) {
const button = this
const {
form
@ -93,7 +90,7 @@ Rails.formSubmitButtonClick = function(e) {
return setData(form, "ujs:submit-button-formmethod", button.getAttribute("formmethod"))
}
Rails.preventInsignificantClick = function(e) {
const preventInsignificantClick = function(e) {
const link = this
const method = (link.getAttribute("data-method") || "GET").toUpperCase()
const data = link.getAttribute("data-params")
@ -103,3 +100,4 @@ Rails.preventInsignificantClick = function(e) {
if (nonPrimaryMouseClick || insignificantMetaClick) { e.stopImmediatePropagation() }
}
export { handleRemoteWithRails, formSubmitButtonClick, preventInsignificantClick }

View File

@ -0,0 +1,164 @@
import {
linkClickSelector,
buttonClickSelector,
inputChangeSelector,
formSubmitSelector,
formInputClickSelector,
formDisableSelector,
formEnableSelector,
fileInputSelector,
linkDisableSelector,
buttonDisableSelector
} from "./utils/constants"
import { ajax, href, isCrossDomain } from "./utils/ajax"
import { cspNonce, loadCSPNonce } from "./utils/csp"
import { csrfToken, csrfParam, CSRFProtection, refreshCSRFTokens } from "./utils/csrf"
import { matches, getData, setData, $ } from "./utils/dom"
import { fire, stopEverything, delegate } from "./utils/event"
import { serializeElement, formElements } from "./utils/form"
import { confirm, handleConfirmWithRails } from "./features/confirm"
import { handleDisabledElement, enableElement, disableElement } from "./features/disable"
import { handleMethodWithRails } from "./features/method"
import { handleRemoteWithRails, formSubmitButtonClick, preventInsignificantClick } from "./features/remote"
const Rails = {
$,
ajax,
buttonClickSelector,
buttonDisableSelector,
confirm,
cspNonce,
csrfToken,
csrfParam,
CSRFProtection,
delegate,
disableElement,
enableElement,
fileInputSelector,
fire,
formElements,
formEnableSelector,
formDisableSelector,
formInputClickSelector,
formSubmitButtonClick,
formSubmitSelector,
getData,
handleDisabledElement,
href,
inputChangeSelector,
isCrossDomain,
linkClickSelector,
linkDisableSelector,
loadCSPNonce,
matches,
preventInsignificantClick,
refreshCSRFTokens,
serializeElement,
setData,
stopEverything
}
// needs to be able to call Rails.confirm in case its overridden
const handleConfirm = handleConfirmWithRails(Rails)
Rails.handleConfirm = handleConfirm
// needs to be able to call Rails.href in case its overridden
const handleMethod = handleMethodWithRails(Rails)
Rails.handleMethod = handleMethod
// needs to be able to call Rails.href in case its overridden
const handleRemote = handleRemoteWithRails(Rails)
Rails.handleRemote = handleRemote
const start = function() {
// Cut down on the number of issues from people inadvertently including
// rails-ujs twice by detecting and raising an error when it happens.
if (window._rails_loaded) { throw new Error("rails-ujs has already been loaded!") }
// This event works the same as the load event, except that it fires every
// time the page is loaded.
// See https://github.com/rails/jquery-ujs/issues/357
// See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
window.addEventListener("pageshow", function() {
$(formEnableSelector).forEach(function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el)
}
})
$(linkDisableSelector).forEach(function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el)
}
})
})
delegate(document, linkDisableSelector, "ajax:complete", enableElement)
delegate(document, linkDisableSelector, "ajax:stopped", enableElement)
delegate(document, buttonDisableSelector, "ajax:complete", enableElement)
delegate(document, buttonDisableSelector, "ajax:stopped", enableElement)
delegate(document, linkClickSelector, "click", preventInsignificantClick)
delegate(document, linkClickSelector, "click", handleDisabledElement)
delegate(document, linkClickSelector, "click", handleConfirm)
delegate(document, linkClickSelector, "click", disableElement)
delegate(document, linkClickSelector, "click", handleRemote)
delegate(document, linkClickSelector, "click", handleMethod)
delegate(document, buttonClickSelector, "click", preventInsignificantClick)
delegate(document, buttonClickSelector, "click", handleDisabledElement)
delegate(document, buttonClickSelector, "click", handleConfirm)
delegate(document, buttonClickSelector, "click", disableElement)
delegate(document, buttonClickSelector, "click", handleRemote)
delegate(document, inputChangeSelector, "change", handleDisabledElement)
delegate(document, inputChangeSelector, "change", handleConfirm)
delegate(document, inputChangeSelector, "change", handleRemote)
delegate(document, formSubmitSelector, "submit", handleDisabledElement)
delegate(document, formSubmitSelector, "submit", handleConfirm)
delegate(document, formSubmitSelector, "submit", handleRemote)
// Normal mode submit
// Slight timeout so that the submit button gets properly serialized
delegate(document, formSubmitSelector, "submit", e => setTimeout((() => disableElement(e)), 13))
delegate(document, formSubmitSelector, "ajax:send", disableElement)
delegate(document, formSubmitSelector, "ajax:complete", enableElement)
delegate(document, formInputClickSelector, "click", preventInsignificantClick)
delegate(document, formInputClickSelector, "click", handleDisabledElement)
delegate(document, formInputClickSelector, "click", handleConfirm)
delegate(document, formInputClickSelector, "click", formSubmitButtonClick)
document.addEventListener("DOMContentLoaded", refreshCSRFTokens)
document.addEventListener("DOMContentLoaded", loadCSPNonce)
return window._rails_loaded = true
}
Rails.start = start
// For backward compatibility
if (typeof jQuery !== "undefined" && jQuery && jQuery.ajax) {
if (jQuery.rails) { throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.") }
jQuery.rails = Rails
jQuery.ajaxPrefilter(function(options, originalOptions, xhr) {
if (!options.crossDomain) { return CSRFProtection(xhr) }
})
}
// This block is to maintain backwards compatibility with the existing
// difference between what happens in a bundler and what happens using a
// sprockets compiler. In the sprockets case, Rails.start() is called
// automatically, but it is not in the ESModule case.
if (typeof exports !== "object" && typeof module === "undefined") {
// The coffeescript bundle would set this at the very top. The Rollup bundle
// doesn't set this until the entire bundle has finished running, so we need
// to make sure its set before firing the rails:attachBindings event for
// backwards compatibility.
window.Rails = Rails
if (fire(document, "rails:attachBindings")) {
start()
}
}
export default Rails

View File

@ -1,86 +0,0 @@
const {
fire, delegate,
getData, $,
refreshCSRFTokens, CSRFProtection,
loadCSPNonce,
enableElement, disableElement, handleDisabledElement,
handleConfirm, preventInsignificantClick,
handleRemote, formSubmitButtonClick,
handleMethod
} = Rails
// For backward compatibility
if (typeof jQuery !== "undefined" && jQuery && jQuery.ajax) {
if (jQuery.rails) { throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.") }
jQuery.rails = Rails
jQuery.ajaxPrefilter(function(options, originalOptions, xhr) {
if (!options.crossDomain) { return CSRFProtection(xhr) }
})
}
Rails.start = function() {
// Cut down on the number of issues from people inadvertently including
// rails-ujs twice by detecting and raising an error when it happens.
if (window._rails_loaded) { throw new Error("rails-ujs has already been loaded!") }
// This event works the same as the load event, except that it fires every
// time the page is loaded.
// See https://github.com/rails/jquery-ujs/issues/357
// See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
window.addEventListener("pageshow", function() {
$(Rails.formEnableSelector).forEach(function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el)
}
})
$(Rails.linkDisableSelector).forEach(function(el) {
if (getData(el, "ujs:disabled")) {
enableElement(el)
}
})
})
delegate(document, Rails.linkDisableSelector, "ajax:complete", enableElement)
delegate(document, Rails.linkDisableSelector, "ajax:stopped", enableElement)
delegate(document, Rails.buttonDisableSelector, "ajax:complete", enableElement)
delegate(document, Rails.buttonDisableSelector, "ajax:stopped", enableElement)
delegate(document, Rails.linkClickSelector, "click", preventInsignificantClick)
delegate(document, Rails.linkClickSelector, "click", handleDisabledElement)
delegate(document, Rails.linkClickSelector, "click", handleConfirm)
delegate(document, Rails.linkClickSelector, "click", disableElement)
delegate(document, Rails.linkClickSelector, "click", handleRemote)
delegate(document, Rails.linkClickSelector, "click", handleMethod)
delegate(document, Rails.buttonClickSelector, "click", preventInsignificantClick)
delegate(document, Rails.buttonClickSelector, "click", handleDisabledElement)
delegate(document, Rails.buttonClickSelector, "click", handleConfirm)
delegate(document, Rails.buttonClickSelector, "click", disableElement)
delegate(document, Rails.buttonClickSelector, "click", handleRemote)
delegate(document, Rails.inputChangeSelector, "change", handleDisabledElement)
delegate(document, Rails.inputChangeSelector, "change", handleConfirm)
delegate(document, Rails.inputChangeSelector, "change", handleRemote)
delegate(document, Rails.formSubmitSelector, "submit", handleDisabledElement)
delegate(document, Rails.formSubmitSelector, "submit", handleConfirm)
delegate(document, Rails.formSubmitSelector, "submit", handleRemote)
// Normal mode submit
// Slight timeout so that the submit button gets properly serialized
delegate(document, Rails.formSubmitSelector, "submit", e => setTimeout((() => disableElement(e)), 13))
delegate(document, Rails.formSubmitSelector, "ajax:send", disableElement)
delegate(document, Rails.formSubmitSelector, "ajax:complete", enableElement)
delegate(document, Rails.formInputClickSelector, "click", preventInsignificantClick)
delegate(document, Rails.formInputClickSelector, "click", handleDisabledElement)
delegate(document, Rails.formInputClickSelector, "click", handleConfirm)
delegate(document, Rails.formInputClickSelector, "click", formSubmitButtonClick)
document.addEventListener("DOMContentLoaded", refreshCSRFTokens)
document.addEventListener("DOMContentLoaded", loadCSPNonce)
return window._rails_loaded = true
}
if ((window.Rails === Rails) && fire(document, "rails:attachBindings")) {
Rails.start()
}

View File

@ -1,8 +1,5 @@
//= require ./csp
//= require ./csrf
//= require ./event
const { cspNonce, CSRFProtection, fire } = Rails
import { cspNonce } from "./csp"
import { CSRFProtection } from "./csrf"
const AcceptHeaders = {
"*": "*/*",
@ -13,7 +10,7 @@ const AcceptHeaders = {
script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
}
Rails.ajax = function(options) {
const ajax = (options) => {
options = prepareOptions(options)
var xhr = createXHR(options, function() {
const response = processResponse(xhr.response != null ? xhr.response : xhr.responseText, xhr.getResponseHeader("Content-Type"))
@ -97,10 +94,10 @@ var processResponse = function(response, type) {
}
// Default way to get an element's href. May be overridden at Rails.href.
Rails.href = element => element.href
const href = element => element.href
// Determines if the request is a cross domain request.
Rails.isCrossDomain = function(url) {
const isCrossDomain = function(url) {
const originAnchor = document.createElement("a")
originAnchor.href = location.href
const urlAnchor = document.createElement("a")
@ -118,3 +115,5 @@ Rails.isCrossDomain = function(url) {
return true
}
}
export { ajax, href, isCrossDomain }

View File

@ -0,0 +1,45 @@
// Link elements bound by rails-ujs
const linkClickSelector = "a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]"
// Button elements bound by rails-ujs
const buttonClickSelector = {
selector: "button[data-remote]:not([form]), button[data-confirm]:not([form])",
exclude: "form button"
}
// Select elements bound by rails-ujs
const inputChangeSelector = "select[data-remote], input[data-remote], textarea[data-remote]"
// Form elements bound by rails-ujs
const formSubmitSelector = "form:not([data-turbo=true])"
// Form input elements bound by rails-ujs
const formInputClickSelector = "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])"
// Form input elements disabled during form submission
const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled"
// Form input elements re-enabled after form submission
const formEnableSelector = "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled"
// Form file input elements
const fileInputSelector = "input[name][type=file]:not([disabled])"
// Link onClick disable selector with possible re-enable after remote submission
const linkDisableSelector = "a[data-disable-with], a[data-disable]"
// Button onClick disable selector with possible re-enable after remote submission
const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]"
export {
linkClickSelector,
buttonClickSelector,
inputChangeSelector,
formSubmitSelector,
formInputClickSelector,
formDisableSelector,
formEnableSelector,
fileInputSelector,
linkDisableSelector,
buttonDisableSelector
}

View File

@ -1,9 +1,11 @@
let nonce = null
Rails.loadCSPNonce = () => {
const loadCSPNonce = () => {
const metaTag = document.querySelector("meta[name=csp-nonce]")
return nonce = metaTag && metaTag.content
}
// Returns the Content-Security-Policy nonce for inline scripts.
Rails.cspNonce = () => nonce || Rails.loadCSPNonce()
const cspNonce = () => nonce || loadCSPNonce()
export { cspNonce, loadCSPNonce }

View File

@ -1,30 +1,30 @@
//= require ./dom
const { $ } = Rails
import { $ } from "./dom"
// Up-to-date Cross-Site Request Forgery token
const csrfToken = (Rails.csrfToken = function() {
const csrfToken = () => {
const meta = document.querySelector("meta[name=csrf-token]")
return meta && meta.content
})
}
// URL param that must contain the CSRF token
const csrfParam = (Rails.csrfParam = function() {
const csrfParam = () => {
const meta = document.querySelector("meta[name=csrf-param]")
return meta && meta.content
})
}
// Make sure that every Ajax request sends the CSRF token
Rails.CSRFProtection = function(xhr) {
const CSRFProtection = (xhr) => {
const token = csrfToken()
if (token) { return xhr.setRequestHeader("X-CSRF-Token", token) }
}
// Make sure that all forms have actual up-to-date tokens (cached forms contain old ones)
Rails.refreshCSRFTokens = function() {
const refreshCSRFTokens = () => {
const token = csrfToken()
const param = csrfParam()
if (token && param) {
return $("form input[name=\"" + param + "\"]").forEach(input => input.value = token)
}
}
export { csrfToken, csrfParam, CSRFProtection, refreshCSRFTokens }

View File

@ -12,7 +12,7 @@ const m = Element.prototype.matches ||
// CSS selector string or
// a JavaScript object with `selector` and `exclude` properties
// Examples: "form", { selector: "form", exclude: "form[data-remote='true']"}
Rails.matches = function(element, selector) {
const matches = function(element, selector) {
if (selector.exclude) {
return m.call(element, selector.selector) && !m.call(element, selector.exclude)
} else {
@ -22,15 +22,17 @@ Rails.matches = function(element, selector) {
// get and set data on a given element using "expando properties"
// See: https://developer.mozilla.org/en-US/docs/Glossary/Expando
const expando = "_ujsData"
const EXPANDO = "_ujsData"
Rails.getData = (element, key) => element[expando] ? element[expando][key] : undefined
const getData = (element, key) => element[EXPANDO] ? element[EXPANDO][key] : undefined
Rails.setData = function(element, key, value) {
if (!element[expando]) { element[expando] = {} }
return element[expando][key] = value
const setData = function(element, key, value) {
if (!element[EXPANDO]) { element[EXPANDO] = {} }
return element[EXPANDO][key] = value
}
// a wrapper for document.querySelectorAll
// returns an Array
Rails.$ = selector => Array.prototype.slice.call(document.querySelectorAll(selector))
const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector))
export { matches, getData, setData, $ }

View File

@ -1,7 +1,6 @@
//= require ./dom
import { matches } from "./dom"
let preventDefault
const { matches } = Rails
// Polyfill for CustomEvent in IE9+
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
@ -38,20 +37,20 @@ if (typeof CustomEvent !== "function") {
// e.g. 'click', 'submit'
// data::
// data you want to pass when you dispatch an event
const fire = (Rails.fire = function(obj, name, data) {
const fire = (obj, name, data) => {
const event = new CustomEvent(
name, {
bubbles: true,
cancelable: true,
detail: data,
detail: data
}
)
obj.dispatchEvent(event)
return !event.defaultPrevented
})
}
// Helper function, needed to provide consistent behavior in IE
Rails.stopEverything = function(e) {
const stopEverything = (e) => {
fire(e.target, "ujs:everythingStopped")
e.preventDefault()
e.stopPropagation()
@ -69,7 +68,7 @@ Rails.stopEverything = function(e) {
// string representing the event e.g. 'submit', 'click'
// handler::
// the event handler to be called
Rails.delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, function(e) {
const delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, function(e) {
let {
target
} = e
@ -79,3 +78,5 @@ Rails.delegate = (element, selector, eventType, handler) => element.addEventList
e.stopPropagation()
}
})
export { fire, stopEverything, delegate }

View File

@ -1,10 +1,8 @@
//= require ./dom
const { matches } = Rails
import { matches } from "./dom"
const toArray = e => Array.prototype.slice.call(e)
Rails.serializeElement = function(element, additionalParam) {
const serializeElement = (element, additionalParam) => {
let inputs = [element]
if (matches(element, "form")) { inputs = toArray(element.elements) }
const params = []
@ -34,10 +32,12 @@ Rails.serializeElement = function(element, additionalParam) {
// Helper function that returns form elements that match the specified CSS selector
// If form is actually a "form" element this will return associated elements outside the from that have
// the html form attribute set
Rails.formElements = function(form, selector) {
const formElements = (form, selector) => {
if (matches(form, "form")) {
return toArray(form.elements).filter(el => matches(el, selector))
} else {
return toArray(form.querySelectorAll(selector))
}
}
export { serializeElement, formElements }

View File

@ -3,9 +3,3 @@ load_paths:
logical_paths:
- rails-ujs.js
build:
logical_paths:
- rails-ujs.js
path: lib/assets/compiled
clean: true

View File

@ -2,17 +2,18 @@
"name": "@rails/ujs",
"version": "7.1.0-alpha",
"description": "Ruby on Rails unobtrusive scripting adapter",
"main": "lib/assets/compiled/rails-ujs.js",
"main": "app/assets/javascripts/rails-ujs.js",
"module": "app/assets/javascripts/rails-ujs.esm.js",
"files": [
"lib/assets/compiled/*.js"
"app/assets/javascripts/*.js"
],
"directories": {
"test": "test"
},
"scripts": {
"build": "bundle exec blade build",
"build": "rollup --config rollup.config.js",
"test": "echo \"See the README: https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts#how-to-run-tests\" && exit 1",
"lint": "coffeelint app/assets/javascripts && eslint test/ujs/public/test"
"lint": "eslint app/javascript"
},
"repository": {
"type": "git",
@ -30,7 +31,9 @@
},
"homepage": "https://rubyonrails.org/",
"devDependencies": {
"coffeelint": "^2.1.0",
"eslint": "^2.13.1"
"eslint": "^4.19.1",
"eslint-plugin-import": "^2.23.4",
"rollup": "^2.53.3",
"rollup-plugin-terser": "^7.0.2"
}
}

View File

@ -0,0 +1,51 @@
import { terser } from "rollup-plugin-terser"
const banner = `
/*
Unobtrusive JavaScript
https://github.com/rails/rails/blob/main/actionview/app/javascript
Released under the MIT license
*/
`
const terserOptions = {
mangle: false,
compress: false,
format: {
beautify: true,
indent_level: 2,
comments: function (node, comment) {
if (comment.type == "comment2") {
// multiline comment
return comment.value.includes("Released under the MIT license")
}
}
}
}
export default [
{
input: "app/javascript/rails-ujs/index.js",
output: {
file: "app/assets/javascripts/rails-ujs.js",
format: "umd",
name: "Rails",
banner,
},
plugins: [
terser(terserOptions)
]
},
{
input: "app/javascript/rails-ujs/index.js",
output: {
file: "app/assets/javascripts/rails-ujs.esm.js",
format: "es",
banner,
},
plugins: [
terser(terserOptions)
]
}
]

View File

@ -534,12 +534,6 @@ Module.new do
f.puts 'require "rails/all"'
end
unless File.exist?("#{RAILS_FRAMEWORK_ROOT}/actionview/lib/assets/compiled/rails-ujs.js")
Dir.chdir("#{RAILS_FRAMEWORK_ROOT}/actionview") do
sh "yarn build"
end
end
assets_path = "#{RAILS_FRAMEWORK_ROOT}/railties/test/isolation/assets"
unless Dir.exist?("#{assets_path}/node_modules")
Dir.chdir(assets_path) do

422
yarn.lock
View File

@ -293,11 +293,6 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=
ajv-keywords@^1.0.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw=
ajv-keywords@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
@ -308,14 +303,6 @@ ajv-keywords@^3.1.0:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=
ajv@^4.7.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
ajv@^5.2.3, ajv@^5.3.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
@ -336,11 +323,6 @@ ajv@^6.1.0, ajv@^6.5.5:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-escapes@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
integrity sha1-06ioOzGapneTZisT52HHkRQiMG4=
ansi-escapes@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
@ -907,7 +889,7 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
@ -992,13 +974,6 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
cli-cursor@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=
dependencies:
restore-cursor "^1.0.1"
cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
@ -1016,28 +991,6 @@ co@^4.6.0:
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
coffeelint@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/coffeelint/-/coffeelint-2.1.0.tgz#af65df3634e999d9ac01480736c36d3cd2f5dad8"
integrity sha1-r2XfNjTpmdmsAUgHNsNtPNL12tg=
dependencies:
coffeescript "^2.1.0"
glob "^7.0.6"
ignore "^3.0.9"
optimist "^0.6.1"
resolve "^0.6.3"
strip-json-comments "^1.0.2"
coffeescript@^2.1.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.3.2.tgz#e854a7020dfe47b7cf4dd412042e32ef1e269810"
integrity sha512-YObiFDoukx7qPBi/K0kUKyntEZDfBQiqs/DbrR1xzASKOBjGT7auD85/DiPeRr9k++lRj7l3uA9TNMLfyfcD/Q==
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@ -1127,7 +1080,7 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.6.0:
concat-stream@^1.5.0, concat-stream@^1.6.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
@ -1294,13 +1247,6 @@ cyclist@~0.2.2:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
d@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=
dependencies:
es5-ext "^0.10.9"
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@ -1318,7 +1264,7 @@ date-now@^0.1.4:
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@ -1427,7 +1373,7 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
doctrine@1.5.0, doctrine@^1.2.2:
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=
@ -1615,36 +1561,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
version "0.10.46"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572"
integrity sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==
dependencies:
es6-iterator "~2.0.3"
es6-symbol "~3.1.1"
next-tick "1"
es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
dependencies:
d "1"
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-map@^0.1.3:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=
dependencies:
d "1"
es5-ext "~0.10.14"
es6-iterator "~2.0.1"
es6-set "~0.1.5"
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
es6-promise@^4.0.3:
version "4.2.5"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
@ -1657,35 +1573,6 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
es6-set@~0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=
dependencies:
d "1"
es5-ext "~0.10.14"
es6-iterator "~2.0.1"
es6-symbol "3.1.1"
event-emitter "~0.3.5"
es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=
dependencies:
d "1"
es5-ext "~0.10.14"
es6-weak-map@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=
dependencies:
d "1"
es5-ext "^0.10.14"
es6-iterator "^2.0.1"
es6-symbol "^3.1.1"
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@ -1696,16 +1583,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
escope@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=
dependencies:
es6-map "^0.1.3"
es6-weak-map "^2.0.1"
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-import-resolver-node@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
@ -1796,46 +1673,7 @@ eslint-visitor-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
eslint@^2.13.1:
version "2.13.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11"
integrity sha1-5MyPoPAJ+4KaquI4VaKTYL4fbBE=
dependencies:
chalk "^1.1.3"
concat-stream "^1.4.6"
debug "^2.1.1"
doctrine "^1.2.2"
es6-map "^0.1.3"
escope "^3.6.0"
espree "^3.1.6"
estraverse "^4.2.0"
esutils "^2.0.2"
file-entry-cache "^1.1.1"
glob "^7.0.3"
globals "^9.2.0"
ignore "^3.1.2"
imurmurhash "^0.1.4"
inquirer "^0.12.0"
is-my-json-valid "^2.10.0"
is-resolvable "^1.0.0"
js-yaml "^3.5.1"
json-stable-stringify "^1.0.0"
levn "^0.3.0"
lodash "^4.0.0"
mkdirp "^0.5.0"
optionator "^0.8.1"
path-is-absolute "^1.0.0"
path-is-inside "^1.0.1"
pluralize "^1.2.1"
progress "^1.1.8"
require-uncached "^1.0.2"
shelljs "^0.6.0"
strip-json-comments "~1.0.1"
table "^3.7.8"
text-table "~0.2.0"
user-home "^2.0.0"
eslint@^4.3.0:
eslint@^4.19.1, eslint@^4.3.0:
version "4.19.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300"
integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==
@ -1879,7 +1717,7 @@ eslint@^4.3.0:
table "4.0.2"
text-table "~0.2.0"
espree@^3.1.6, espree@^3.5.4:
espree@^3.5.4:
version "3.5.4"
resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7"
integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==
@ -1906,7 +1744,7 @@ esrecurse@^4.1.0:
dependencies:
estraverse "^4.1.0"
estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=
@ -1926,14 +1764,6 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
event-emitter@~0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
dependencies:
d "1"
es5-ext "~0.10.14"
eventemitter3@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
@ -1982,11 +1812,6 @@ exists-stat@1.0.0:
resolved "https://registry.yarnpkg.com/exists-stat/-/exists-stat-1.0.0.tgz#0660e3525a2e89d9e446129440c272edfa24b529"
integrity sha1-BmDjUlouidnkRhKUQMJy7foktSk=
exit-hook@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=
expand-braces@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea"
@ -2109,14 +1934,6 @@ figgy-pudding@^3.1.0, figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
figures@^1.3.5:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
dependencies:
escape-string-regexp "^1.0.5"
object-assign "^4.1.0"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
@ -2124,14 +1941,6 @@ figures@^2.0.0:
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^1.1.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8"
integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=
dependencies:
flat-cache "^1.2.1"
object-assign "^4.0.1"
file-entry-cache@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
@ -2323,20 +2132,6 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
generate-function@^2.0.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==
dependencies:
is-property "^1.0.2"
generate-object-property@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=
dependencies:
is-property "^1.0.0"
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
@ -2373,7 +2168,7 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@ -2422,11 +2217,6 @@ globals@^11.0.1:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249"
integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==
globals@^9.2.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
@ -2624,7 +2414,7 @@ iferr@^0.1.5:
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
ignore@^3.0.9, ignore@^3.1.2, ignore@^3.3.3:
ignore@^3.3.3:
version "3.3.10"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
@ -2662,25 +2452,6 @@ ini@^1.3.4:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
inquirer@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=
dependencies:
ansi-escapes "^1.1.0"
ansi-regex "^2.0.0"
chalk "^1.0.0"
cli-cursor "^1.0.1"
cli-width "^2.0.0"
figures "^1.3.5"
lodash "^4.3.0"
readline2 "^1.0.1"
run-async "^0.1.0"
rx-lite "^3.1.2"
string-width "^1.0.1"
strip-ansi "^3.0.0"
through "^2.3.6"
inquirer@^3.0.6:
version "3.3.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
@ -2826,13 +2597,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
dependencies:
number-is-nan "^1.0.0"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
@ -2857,22 +2621,6 @@ is-module@^1.0.0:
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
is-my-ip-valid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824"
integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==
is-my-json-valid@^2.10.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175"
integrity sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==
dependencies:
generate-function "^2.0.0"
generate-object-property "^1.1.0"
is-my-ip-valid "^1.0.0"
jsonpointer "^4.0.0"
xtend "^4.0.0"
is-negative-zero@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
@ -2907,11 +2655,6 @@ is-promise@^2.1.0:
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
is-property@^1.0.0, is-property@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=
is-reference@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
@ -3022,7 +2765,7 @@ js-tokens@^4.0.0:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.5.1, js-yaml@^3.9.1:
js-yaml@^3.9.1:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==
@ -3060,13 +2803,6 @@ json-stable-stringify-without-jsonify@^1.0.1:
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=
dependencies:
jsonify "~0.0.0"
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@ -3084,16 +2820,6 @@ json5@^2.2.0:
dependencies:
minimist "^1.2.5"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
jsonpointer@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk=
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@ -3255,7 +2981,7 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash@4.17.11, lodash@^4.0.0, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0:
lodash@4.17.11, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.8.0:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
@ -3461,7 +3187,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@ -3497,11 +3223,6 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
mute-stream@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
@ -3544,11 +3265,6 @@ neo-async@^2.5.0:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==
next-tick@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
@ -3617,17 +3333,12 @@ null-check@^1.0.0:
resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
object-assign@^4.0.1, object-assign@^4.1.0:
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@ -3703,11 +3414,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
onetime@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=
onetime@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
@ -3723,7 +3429,7 @@ optimist@^0.6.1:
minimist "~0.0.1"
wordwrap "~0.0.2"
optionator@^0.8.1, optionator@^0.8.2:
optionator@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=
@ -3740,11 +3446,6 @@ os-browserify@^0.3.0:
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@ -3889,7 +3590,7 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
path-is-inside@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
@ -3994,11 +3695,6 @@ pkg-up@^2.0.0:
dependencies:
find-up "^2.1.0"
pluralize@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=
pluralize@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
@ -4024,11 +3720,6 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
progress@^1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=
progress@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31"
@ -4242,15 +3933,6 @@ readdirp@^2.0.0:
micromatch "^3.1.10"
readable-stream "^2.0.2"
readline2@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
mute-stream "0.0.5"
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@ -4310,7 +3992,7 @@ request@2.88.0:
tunnel-agent "^0.6.0"
uuid "^3.3.2"
require-uncached@^1.0.2, require-uncached@^1.0.3:
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=
@ -4348,11 +4030,6 @@ resolve@1.5.0:
dependencies:
path-parse "^1.0.5"
resolve@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46"
integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY=
resolve@^1.13.1, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
@ -4368,14 +4045,6 @@ resolve@^1.5.0, resolve@^1.6.0:
dependencies:
path-parse "^1.0.5"
restore-cursor@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=
dependencies:
exit-hook "^1.0.0"
onetime "^1.0.0"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@ -4419,7 +4088,7 @@ rollup-plugin-terser@^7.0.2:
serialize-javascript "^4.0.0"
terser "^5.0.0"
rollup@^2.35.1:
rollup@^2.35.1, rollup@^2.53.3:
version "2.53.3"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.53.3.tgz#14b0e57f0874d4ad23bdbb13050cf70bcd1eabf7"
integrity sha512-79QIGP5DXz5ZHYnCPi3tLz+elOQi6gudp9YINdaJdjG0Yddubo6JRFUM//qCZ0Bap/GJrsUoEBVdSOc4AkMlRA==
@ -4431,13 +4100,6 @@ rsvp@^3.3.3:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
run-async@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=
dependencies:
once "^1.3.0"
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
@ -4464,11 +4126,6 @@ rx-lite@*, rx-lite@^4.0.8:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@ -4603,11 +4260,6 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
shelljs@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
@ -4622,11 +4274,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
slice-ansi@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=
slice-ansi@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
@ -4892,16 +4539,7 @@ streamroller@0.7.0:
mkdirp "^0.5.1"
readable-stream "^2.3.0"
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@ -4963,11 +4601,6 @@ strip-eof@^1.0.0:
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
strip-json-comments@^1.0.2, strip-json-comments@~1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
@ -5004,18 +4637,6 @@ table@4.0.2:
slice-ansi "1.0.0"
string-width "^2.1.1"
table@^3.7.8:
version "3.8.3"
resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=
dependencies:
ajv "^4.7.0"
ajv-keywords "^1.0.0"
chalk "^1.1.1"
lodash "^4.0.0"
slice-ansi "0.0.4"
string-width "^2.0.0"
tapable@^1.0.0, tapable@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e"
@ -5294,13 +4915,6 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
user-home@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8=
dependencies:
os-homedir "^1.0.0"
useragent@2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"