Merge pull request #45546 from skipkayhil/decaffeinate-ujs

Convert rails-ujs to ES2015 modules
This commit is contained in:
Rafael Mendonça França 2022-09-14 18:59:58 -04:00 committed by GitHub
commit 3d1f38fa30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2198 additions and 1110 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

@ -1,39 +0,0 @@
#= require ./rails-ujs/BANNER
#= export Rails
#= require_self
#= require_tree ./rails-ujs/utils
#= require_tree ./rails-ujs/features
#= require ./rails-ujs/start
@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

@ -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,5 +0,0 @@
/*
Unobtrusive JavaScript
https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts
Released under the MIT license
*/

View File

@ -1,30 +0,0 @@
#= require_tree ../utils
{ fire, stopEverything } = Rails
Rails.handleConfirm = (e) ->
stopEverything(e) unless allowAction(this)
# Default confirm dialog, may be overridden with custom confirm dialog in Rails.confirm
Rails.confirm = (message, element) ->
confirm(message)
# For 'data-confirm' attribute:
# - Fires `confirm` event
# - Shows the confirmation dialog
# - Fires the `confirm:complete` event
#
# Returns `true` if no function stops the chain and user chose yes `false` otherwise.
# 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.
allowAction = (element) ->
message = element.getAttribute('data-confirm')
return true unless message
answer = false
if fire(element, 'confirm')
try answer = Rails.confirm(message, element)
callback = fire(element, 'confirm:complete', [answer])
answer and callback

View File

@ -1,93 +0,0 @@
#= require_tree ../utils
{ matches, getData, setData, stopEverything, formElements } = Rails
Rails.handleDisabledElement = (e) ->
element = this
stopEverything(e) if element.disabled
# Unified function to enable an element (link, button and form)
Rails.enableElement = (e) ->
if e instanceof Event
return if isXhrRedirect(e)
element = e.target
else
element = e
if matches(element, Rails.linkDisableSelector)
enableLinkElement(element)
else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formEnableSelector)
enableFormElement(element)
else if matches(element, Rails.formSubmitSelector)
enableFormElements(element)
# Unified function to disable an element (link, button and form)
Rails.disableElement = (e) ->
element = if e instanceof Event then e.target else e
if matches(element, Rails.linkDisableSelector)
disableLinkElement(element)
else if matches(element, Rails.buttonDisableSelector) or matches(element, Rails.formDisableSelector)
disableFormElement(element)
else if matches(element, Rails.formSubmitSelector)
disableFormElements(element)
# Replace element's html with the 'data-disable-with' after storing original html
# and prevent clicking on it
disableLinkElement = (element) ->
return if getData(element, 'ujs:disabled')
replacement = element.getAttribute('data-disable-with')
if replacement?
setData(element, 'ujs:enable-with', element.innerHTML) # store enabled state
element.innerHTML = replacement
element.addEventListener('click', stopEverything) # prevent further clicking
setData(element, 'ujs:disabled', true)
# Restore element to its original state which was disabled by 'disableLinkElement' above
enableLinkElement = (element) ->
originalText = getData(element, 'ujs:enable-with')
if originalText?
element.innerHTML = originalText # set to old enabled state
setData(element, 'ujs:enable-with', null) # clean up cache
element.removeEventListener('click', stopEverything) # enable element
setData(element, 'ujs:disabled', null)
# Disables form elements:
# - Caches element value in 'ujs:enable-with' data store
# - Replaces element text with value of 'data-disable-with' attribute
# - Sets disabled property to true
disableFormElements = (form) ->
formElements(form, Rails.formDisableSelector).forEach(disableFormElement)
disableFormElement = (element) ->
return if getData(element, 'ujs:disabled')
replacement = element.getAttribute('data-disable-with')
if replacement?
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
setData(element, 'ujs:disabled', true)
# 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
enableFormElements = (form) ->
formElements(form, Rails.formEnableSelector).forEach(enableFormElement)
enableFormElement = (element) ->
originalText = getData(element, 'ujs:enable-with')
if originalText?
if matches(element, 'button')
element.innerHTML = originalText
else
element.value = originalText
setData(element, 'ujs:enable-with', null) # clean up cache
element.disabled = false
setData(element, 'ujs:disabled', null)
isXhrRedirect = (event) ->
xhr = event.detail?[0]
xhr?.getResponseHeader("X-Xhr-Redirect")?

View File

@ -1,34 +0,0 @@
#= require_tree ../utils
{ stopEverything } = Rails
# 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 = (e) ->
link = this
method = link.getAttribute('data-method')
return unless method
href = Rails.href(link)
csrfToken = Rails.csrfToken()
csrfParam = Rails.csrfParam()
form = document.createElement('form')
formContent = "<input name='_method' value='#{method}' type='hidden' />"
if csrfParam? and csrfToken? and not Rails.isCrossDomain(href)
formContent += "<input name='#{csrfParam}' value='#{csrfToken}' type='hidden' />"
# Must trigger submit by click on a button, else "submit" event handler won't work!
# https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
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)

View File

@ -1,93 +0,0 @@
#= require_tree ../utils
{
matches, getData, setData
fire, stopEverything
ajax, isCrossDomain
serializeElement
} = Rails
# Checks "data-remote" if true to handle the request through a XHR request.
isRemote = (element) ->
value = element.getAttribute('data-remote')
value? and value isnt 'false'
# Submits "remote" forms and links with ajax
Rails.handleRemote = (e) ->
element = this
return true unless isRemote(element)
unless fire(element, 'ajax:before')
fire(element, 'ajax:stopped')
return false
withCredentials = element.getAttribute('data-with-credentials')
dataType = element.getAttribute('data-type') or 'script'
if matches(element, Rails.formSubmitSelector)
# memoized value from clicked submit button
button = getData(element, 'ujs:submit-button')
method = getData(element, 'ujs:submit-button-formmethod') or element.getAttribute('method') or "get"
url = getData(element, 'ujs:submit-button-formaction') or element.getAttribute('action') or location.href
# strip query string if it's a GET request
url = url.replace(/\?.*$/, '') if method.toUpperCase() is 'GET'
if element.enctype is 'multipart/form-data'
data = new FormData(element)
data.append(button.name, button.value) if button?
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, Rails.buttonClickSelector) or matches(element, Rails.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 or 'GET'
url: url
data: data
dataType: dataType
# stopping the "ajax:beforeSend" event will cancel the ajax request
beforeSend: (xhr, options) ->
if fire(element, 'ajax:beforeSend', [xhr, options])
fire(element, 'ajax:send', [xhr])
else
fire(element, 'ajax:stopped')
return false
success: (args...) -> fire(element, 'ajax:success', args)
error: (args...) -> fire(element, 'ajax:error', args)
complete: (args...) -> fire(element, 'ajax:complete', args)
crossDomain: isCrossDomain(url)
withCredentials: withCredentials? and withCredentials isnt 'false'
)
stopEverything(e)
Rails.formSubmitButtonClick = (e) ->
button = this
form = button.form
return unless form
# Register the pressed submit button
setData(form, 'ujs:submit-button', name: button.name, value: button.value) if button.name
# Save attributes from button
setData(form, 'ujs:formnovalidate-button', button.formNoValidate)
setData(form, 'ujs:submit-button-formaction', button.getAttribute('formaction'))
setData(form, 'ujs:submit-button-formmethod', button.getAttribute('formmethod'))
Rails.preventInsignificantClick = (e) ->
link = this
method = (link.getAttribute('data-method') or 'GET').toUpperCase()
data = link.getAttribute('data-params')
metaClick = e.metaKey or e.ctrlKey
insignificantMetaClick = metaClick and method is 'GET' and not data
nonPrimaryMouseClick = e.button? and e.button isnt 0
e.stopImmediatePropagation() if nonPrimaryMouseClick or insignificantMetaClick

View File

@ -1,75 +0,0 @@
{
fire, delegate
getData, $
refreshCSRFTokens, CSRFProtection
loadCSPNonce
enableElement, disableElement, handleDisabledElement
handleConfirm, preventInsignificantClick
handleRemote, formSubmitButtonClick,
handleMethod
} = Rails
# For backward compatibility
if jQuery? and jQuery.ajax?
throw new Error('If you load both jquery_ujs and rails-ujs, use rails-ujs only.') if jQuery.rails
jQuery.rails = Rails
jQuery.ajaxPrefilter (options, originalOptions, xhr) ->
CSRFProtection(xhr) unless options.crossDomain
Rails.start = ->
# Cut down on the number of issues from people inadvertently including
# rails-ujs twice by detecting and raising an error when it happens.
throw new Error('rails-ujs has already been loaded!') if window._rails_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', ->
$(Rails.formEnableSelector).forEach (el) ->
enableElement(el) if getData(el, 'ujs:disabled')
$(Rails.linkDisableSelector).forEach (el) ->
enableElement(el) if getData(el, 'ujs:disabled')
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)
window._rails_loaded = true
if window.Rails is Rails and fire(document, 'rails:attachBindings')
Rails.start()

View File

@ -1,98 +0,0 @@
#= require ./csp
#= require ./csrf
#= require ./event
{ cspNonce, CSRFProtection, fire } = Rails
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'
Rails.ajax = (options) ->
options = prepareOptions(options)
xhr = createXHR options, ->
response = processResponse(xhr.response ? xhr.responseText, xhr.getResponseHeader('Content-Type'))
if xhr.status // 100 == 2
options.success?(response, xhr.statusText, xhr)
else
options.error?(response, xhr.statusText, xhr)
options.complete?(xhr, xhr.statusText)
if options.beforeSend? && !options.beforeSend(xhr, options)
return false
if xhr.readyState is XMLHttpRequest.OPENED
xhr.send(options.data)
prepareOptions = (options) ->
options.url = options.url or location.href
options.type = options.type.toUpperCase()
# append data to url if it's a GET request
if options.type is 'GET' and options.data
if options.url.indexOf('?') < 0
options.url += '?' + options.data
else
options.url += '&' + options.data
# Use "*" as default dataType
options.dataType = '*' unless AcceptHeaders[options.dataType]?
options.accept = AcceptHeaders[options.dataType]
options.accept += ', */*; q=0.01' if options.dataType isnt '*'
options
createXHR = (options, done) ->
xhr = new XMLHttpRequest()
# Open and set up xhr
xhr.open(options.type, options.url, true)
xhr.setRequestHeader('Accept', options.accept)
# Set Content-Type only when sending a string
# Sending FormData will automatically set Content-Type to multipart/form-data
if typeof options.data is 'string'
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
unless options.crossDomain
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
# Add X-CSRF-Token
CSRFProtection(xhr)
xhr.withCredentials = !!options.withCredentials
xhr.onreadystatechange = ->
done(xhr) if xhr.readyState is XMLHttpRequest.DONE
xhr
processResponse = (response, type) ->
if typeof response is 'string' and typeof type is 'string'
if type.match(/\bjson\b/)
try response = JSON.parse(response)
else if type.match(/\b(?:java|ecma)script\b/)
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/)
parser = new DOMParser()
type = type.replace(/;.+/, '') # remove something like ';charset=utf-8'
try response = parser.parseFromString(response, type)
response
# Default way to get an element's href. May be overridden at Rails.href.
Rails.href = (element) -> element.href
# Determines if the request is a cross domain request.
Rails.isCrossDomain = (url) ->
originAnchor = document.createElement('a')
originAnchor.href = location.href
urlAnchor = document.createElement('a')
try
urlAnchor.href = url
# If URL protocol is false or is a string containing a single colon
# *and* host are false, assume it is not a cross-domain request
# (should only be the case for IE7 and IE compatibility mode).
# Otherwise, evaluate protocol and host of the URL against the origin
# protocol and host.
!(((!urlAnchor.protocol || urlAnchor.protocol == ':') && !urlAnchor.host) ||
(originAnchor.protocol + '//' + originAnchor.host == urlAnchor.protocol + '//' + urlAnchor.host))
catch e
# If there is an error parsing the URL, assume it is crossDomain.
true

View File

@ -1,8 +0,0 @@
nonce = null
Rails.loadCSPNonce = ->
nonce = document.querySelector("meta[name=csp-nonce]")?.content
# Returns the Content-Security-Policy nonce for inline scripts.
Rails.cspNonce = ->
nonce ? Rails.loadCSPNonce()

View File

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

View File

@ -1,35 +0,0 @@
m = Element.prototype.matches or
Element.prototype.matchesSelector or
Element.prototype.mozMatchesSelector or
Element.prototype.msMatchesSelector or
Element.prototype.oMatchesSelector or
Element.prototype.webkitMatchesSelector
# Checks if the given native dom element matches the selector
# element::
# native DOM element
# selector::
# CSS selector string or
# a JavaScript object with `selector` and `exclude` properties
# Examples: "form", { selector: "form", exclude: "form[data-remote='true']"}
Rails.matches = (element, selector) ->
if selector.exclude?
m.call(element, selector.selector) and not m.call(element, selector.exclude)
else
m.call(element, selector)
# get and set data on a given element using "expando properties"
# See: https://developer.mozilla.org/en-US/docs/Glossary/Expando
expando = '_ujsData'
Rails.getData = (element, key) ->
element[expando]?[key]
Rails.setData = (element, key, value) ->
element[expando] ?= {}
element[expando][key] = value
# a wrapper for document.querySelectorAll
# returns an Array
Rails.$ = (selector) ->
Array.prototype.slice.call(document.querySelectorAll(selector))

View File

@ -1,68 +0,0 @@
#= require ./dom
{ matches } = Rails
# Polyfill for CustomEvent in IE9+
# https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
CustomEvent = window.CustomEvent
if typeof CustomEvent isnt 'function'
CustomEvent = (event, params) ->
evt = document.createEvent('CustomEvent')
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
evt
CustomEvent.prototype = window.Event.prototype
# Fix setting `defaultPrevented` when `preventDefault()` is called
# http://stackoverflow.com/questions/23349191/event-preventdefault-is-not-working-in-ie-11-for-custom-events
{ preventDefault } = CustomEvent.prototype
CustomEvent.prototype.preventDefault = ->
result = preventDefault.call(this)
if @cancelable and not @defaultPrevented
Object.defineProperty(this, 'defaultPrevented', get: -> true)
result
# Triggers a custom event on an element and returns false if the event result is false
# obj::
# a native DOM element
# name::
# string that corresponds to the event you want to trigger
# e.g. 'click', 'submit'
# data::
# data you want to pass when you dispatch an event
fire = Rails.fire = (obj, name, data) ->
event = new CustomEvent(
name,
bubbles: true,
cancelable: true,
detail: data,
)
obj.dispatchEvent(event)
!event.defaultPrevented
# Helper function, needed to provide consistent behavior in IE
Rails.stopEverything = (e) ->
fire(e.target, 'ujs:everythingStopped')
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
# Delegates events
# to a specified parent `element`, which fires event `handler`
# for the specified `selector` when an event of `eventType` is triggered
# element::
# parent element that will listen for events e.g. document
# selector::
# CSS selector; or an object that has `selector` and `exclude` properties (see: Rails.matches)
# eventType::
# string representing the event e.g. 'submit', 'click'
# handler::
# the event handler to be called
Rails.delegate = (element, selector, eventType, handler) ->
element.addEventListener eventType, (e) ->
target = e.target
target = target.parentNode until not (target instanceof Element) or matches(target, selector)
if target instanceof Element and handler.call(target, e) == false
e.preventDefault()
e.stopPropagation()

View File

@ -1,37 +0,0 @@
#= require ./dom
{ matches } = Rails
toArray = (e) -> Array.prototype.slice.call(e)
Rails.serializeElement = (element, additionalParam) ->
inputs = [element]
inputs = toArray(element.elements) if matches(element, 'form')
params = []
inputs.forEach (input) ->
return if !input.name || input.disabled
return if matches(input, 'fieldset[disabled] *')
if matches(input, 'select')
toArray(input.options).forEach (option) ->
params.push(name: input.name, value: option.value) if option.selected
else if input.checked or ['radio', 'checkbox', 'submit'].indexOf(input.type) == -1
params.push(name: input.name, value: input.value)
params.push(additionalParam) if additionalParam
params.map (param) ->
if param.name?
"#{encodeURIComponent(param.name)}=#{encodeURIComponent(param.value)}"
else
param
.join('&')
# 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 = (form, selector) ->
if matches(form, 'form')
toArray(form.elements).filter (el) -> matches(el, selector)
else
toArray(form.querySelectorAll(selector))

View File

@ -0,0 +1,33 @@
import { fire, stopEverything } from "../utils/event"
const handleConfirmWithRails = (rails) => function(e) {
if (!allowAction(this, rails)) { stopEverything(e) }
}
// Default confirm dialog, may be overridden with custom confirm dialog in Rails.confirm
const confirm = (message, element) => window.confirm(message)
// For 'data-confirm' attribute:
// - Fires `confirm` event
// - Shows the confirmation dialog
// - Fires the `confirm:complete` event
//
// Returns `true` if no function stops the chain and user chose yes `false` otherwise.
// 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, 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 */ }
callback = fire(element, "confirm:complete", [answer])
}
return answer && callback
}
export { handleConfirmWithRails, confirm }

View File

@ -0,0 +1,118 @@
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 handleDisabledElement = function(e) {
const element = this
if (element.disabled) { stopEverything(e) }
}
// Unified function to enable an element (link, button and form)
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)
}
}
// Unified function to disable an element (link, button and form)
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)
}
}
// Replace element's html with the 'data-disable-with' after storing original html
// and prevent clicking on it
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) // store enabled state
element.innerHTML = replacement
}
element.addEventListener("click", stopEverything) // prevent further clicking
return setData(element, "ujs:disabled", true)
}
// Restore element to its original state which was disabled by 'disableLinkElement' above
var enableLinkElement = function(element) {
const originalText = getData(element, "ujs:enable-with")
if (originalText != null) {
element.innerHTML = originalText // set to old enabled state
setData(element, "ujs:enable-with", null) // clean up cache
}
element.removeEventListener("click", stopEverything) // enable element
return setData(element, "ujs:disabled", null)
}
// Disables form elements:
// - 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, 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)
}
// 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, 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) // clean up cache
}
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")
}
export { handleDisabledElement, enableElement, disableElement }

View File

@ -0,0 +1,38 @@
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>
const handleMethodWithRails = (rails) => function(e) {
const link = this
const method = link.getAttribute("data-method")
if (!method) { return }
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 && !isCrossDomain(href)) {
formContent += `<input name='${csrfParam}' value='${csrfToken}' type='hidden' />`
}
// Must trigger submit by click on a button, else "submit" event handler won't work!
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
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)
}
export { handleMethodWithRails }

View File

@ -0,0 +1,103 @@
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) {
const value = element.getAttribute("data-remote")
return (value != null) && (value !== "false")
}
// Submits "remote" forms and links with ajax
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)) {
// memoized value from clicked submit button
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
// strip query string if it's a GET request
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,
data,
dataType,
// stopping the "ajax:beforeSend" event will cancel the ajax request
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
} = button
if (!form) { return }
// Register the pressed submit button
if (button.name) { setData(form, "ujs:submit-button", {name: button.name, value: button.value}) }
// Save attributes from button
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() }
}
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

@ -0,0 +1,119 @@
import { cspNonce } from "./csp"
import { CSRFProtection } from "./csrf"
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()
// append data to url if it's a GET request
if ((options.type === "GET") && options.data) {
if (options.url.indexOf("?") < 0) {
options.url += "?" + options.data
} else {
options.url += "&" + options.data
}
}
// Use "*" as default dataType
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()
// Open and set up xhr
xhr.open(options.type, options.url, true)
xhr.setRequestHeader("Accept", options.accept)
// Set Content-Type only when sending a string
// Sending FormData will automatically set Content-Type to multipart/form-data
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")
// Add X-CSRF-Token
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) { /* do nothing */ }
} 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(/;.+/, "") // remove something like ';charset=utf-8'
try { response = parser.parseFromString(response, type) } catch (error1) { /* do nothing */ }
}
}
return response
}
// Default way to get an element's href. May be overridden at Rails.href.
const href = element => element.href
// Determines if the request is a cross domain request.
const isCrossDomain = function(url) {
const originAnchor = document.createElement("a")
originAnchor.href = location.href
const urlAnchor = document.createElement("a")
try {
urlAnchor.href = url
// If URL protocol is false or is a string containing a single colon
// *and* host are false, assume it is not a cross-domain request
// (should only be the case for IE7 and IE compatibility mode).
// Otherwise, evaluate protocol and host of the URL against the origin
// protocol and host.
return !(((!urlAnchor.protocol || (urlAnchor.protocol === ":")) && !urlAnchor.host) ||
((originAnchor.protocol + "//" + originAnchor.host) === (urlAnchor.protocol + "//" + urlAnchor.host)))
} catch (e) {
// If there is an error parsing the URL, assume it is crossDomain.
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

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

View File

@ -0,0 +1,30 @@
import { $ } from "./dom"
// Up-to-date Cross-Site Request Forgery token
const csrfToken = () => {
const meta = document.querySelector("meta[name=csrf-token]")
return meta && meta.content
}
// URL param that must contain the CSRF token
const csrfParam = () => {
const meta = document.querySelector("meta[name=csrf-param]")
return meta && meta.content
}
// Make sure that every Ajax request sends the CSRF token
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)
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

@ -0,0 +1,38 @@
const m = Element.prototype.matches ||
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector
// Checks if the given native dom element matches the selector
// element::
// native DOM element
// selector::
// CSS selector string or
// a JavaScript object with `selector` and `exclude` properties
// Examples: "form", { selector: "form", exclude: "form[data-remote='true']"}
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)
}
}
// 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 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
}
// a wrapper for document.querySelectorAll
// returns an Array
const $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector))
export { matches, getData, setData, $ }

View File

@ -0,0 +1,82 @@
import { matches } from "./dom"
let preventDefault
// Polyfill for CustomEvent in IE9+
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
let {
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;
// Fix setting `defaultPrevented` when `preventDefault()` is called
// http://stackoverflow.com/questions/23349191/event-preventdefault-is-not-working-in-ie-11-for-custom-events
({ 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
}
}
// Triggers a custom event on an element and returns false if the event result is false
// obj::
// a native DOM element
// name::
// string that corresponds to the event you want to trigger
// e.g. 'click', 'submit'
// data::
// data you want to pass when you dispatch an event
const fire = (obj, name, data) => {
const event = new CustomEvent(
name, {
bubbles: true,
cancelable: true,
detail: data
}
)
obj.dispatchEvent(event)
return !event.defaultPrevented
}
// Helper function, needed to provide consistent behavior in IE
const stopEverything = (e) => {
fire(e.target, "ujs:everythingStopped")
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
}
// Delegates events
// to a specified parent `element`, which fires event `handler`
// for the specified `selector` when an event of `eventType` is triggered
// element::
// parent element that will listen for events e.g. document
// selector::
// CSS selector; or an object that has `selector` and `exclude` properties (see: Rails.matches)
// eventType::
// string representing the event e.g. 'submit', 'click'
// handler::
// the event handler to be called
const delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, function(e) {
let {
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()
}
})
export { fire, stopEverything, delegate }

View File

@ -0,0 +1,43 @@
import { matches } from "./dom"
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("&")
}
// 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
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"