diff --git a/.circleci/config.yml b/.circleci/config.yml index b261515250..9156f57772 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -93,8 +93,8 @@ build_machine_environment: &build_machine_environment SELF_TEST_TOOL_NODE_FLAGS: " " # Variables for load-balancing - NUM_GROUPS: 11 - RUNNING_AVG_LENGTH: 5 + NUM_GROUPS: 12 + RUNNING_AVG_LENGTH: 6 jobs: Get Ready: @@ -153,8 +153,8 @@ jobs: ../meteor npx tsc --noEmit popd ./meteor --get-ready - # shouldn't take longer than 20 minutes - no_output_timeout: 20m + # shouldn't take longer than 60 minutes + no_output_timeout: 60m - run: <<: *run_save_node_bin - persist_to_workspace: @@ -647,6 +647,211 @@ jobs: - store_artifacts: path: /tmp/memuse.txt + Test Browserstack 1: + <<: *build_machine_environment + steps: + - run: + <<: *run_log_mem_use + - run: + <<: *run_env_change + - attach_workspace: + at: . + - run: + name: "Print environment" + command: printenv + - run: + name: "Running self-test (Test Browserstack 1)" + command: | + TEST_GROUP='css hot code push'; + echo $TEST_GROUP; + eval $PRE_TEST_COMMANDS; + ./meteor self-test \ + "$TEST_GROUP" \ + --browserstack \ + --retries ${METEOR_SELF_TEST_RETRIES} \ + --exclude "${SELF_TEST_EXCLUDE}" \ + --headless \ + --junit ./tmp/results/junit/bs1.xml \ + --without-tag "custom-warehouse" + no_output_timeout: 40m + - run: + <<: *run_save_node_bin + - store_test_results: + path: ./tmp/results + - persist_to_workspace: + root: . + paths: ./tmp/results/junit + - store_artifacts: + path: ./tmp/results + - store_artifacts: + path: /tmp/core_dumps + - store_artifacts: + path: /tmp/memuse.txt + + Test Browserstack 2: + <<: *build_machine_environment + steps: + - run: + <<: *run_log_mem_use + - run: + <<: *run_env_change + - attach_workspace: + at: . + - run: + name: "Print environment" + command: printenv + - run: + name: "Running self-test (Test Browserstack 2)" + command: | + TEST_GROUP='custom minifier - devel vs prod'; + echo $TEST_GROUP; + eval $PRE_TEST_COMMANDS; + ./meteor self-test \ + "$TEST_GROUP" \ + --browserstack \ + --retries ${METEOR_SELF_TEST_RETRIES} \ + --exclude "${SELF_TEST_EXCLUDE}" \ + --headless \ + --junit ./tmp/results/junit/bs2.xml \ + --without-tag "custom-warehouse" + no_output_timeout: 40m + - run: + <<: *run_save_node_bin + - store_test_results: + path: ./tmp/results + - persist_to_workspace: + root: . + paths: ./tmp/results/junit + - store_artifacts: + path: ./tmp/results + - store_artifacts: + path: /tmp/core_dumps + - store_artifacts: + path: /tmp/memuse.txt + + Test Browserstack 3: + <<: *build_machine_environment + steps: + - run: + <<: *run_log_mem_use + - run: + <<: *run_env_change + - attach_workspace: + at: . + - run: + name: "Print environment" + command: printenv + - run: + name: "Running self-test (Test Browserstack 3)" + command: | + TEST_GROUP='versioning hot code push'; + echo $TEST_GROUP; + eval $PRE_TEST_COMMANDS; + ./meteor self-test \ + "$TEST_GROUP" \ + --browserstack \ + --retries ${METEOR_SELF_TEST_RETRIES} \ + --exclude "${SELF_TEST_EXCLUDE}" \ + --headless \ + --junit ./tmp/results/junit/bs3.xml \ + --without-tag "custom-warehouse" + no_output_timeout: 40m + - run: + <<: *run_save_node_bin + - store_test_results: + path: ./tmp/results + - persist_to_workspace: + root: . + paths: ./tmp/results/junit + - store_artifacts: + path: ./tmp/results + - store_artifacts: + path: /tmp/core_dumps + - store_artifacts: + path: /tmp/memuse.txt + + Test Browserstack 4: + <<: *build_machine_environment + steps: + - run: + <<: *run_log_mem_use + - run: + <<: *run_env_change + - attach_workspace: + at: . + - run: + name: "Print environment" + command: printenv + - run: + name: "Running self-test (Test Browserstack 4)" + command: | + TEST_GROUP='javascript hot code push'; + echo $TEST_GROUP; + eval $PRE_TEST_COMMANDS; + ./meteor self-test \ + "$TEST_GROUP" \ + --browserstack \ + --retries ${METEOR_SELF_TEST_RETRIES} \ + --exclude "${SELF_TEST_EXCLUDE}" \ + --headless \ + --junit ./tmp/results/junit/bs4.xml \ + --without-tag "custom-warehouse" + no_output_timeout: 40m + - run: + <<: *run_save_node_bin + - store_test_results: + path: ./tmp/results + - persist_to_workspace: + root: . + paths: ./tmp/results/junit + - store_artifacts: + path: ./tmp/results + - store_artifacts: + path: /tmp/core_dumps + - store_artifacts: + path: /tmp/memuse.txt + + Test Browserstack 5: + <<: *build_machine_environment + steps: + - run: + <<: *run_log_mem_use + - run: + <<: *run_env_change + - attach_workspace: + at: . + - run: + name: "Print environment" + command: printenv + - run: + name: "Running self-test (Test Browserstack 5)" + command: | + TEST_GROUP='add packages client archs'; + echo $TEST_GROUP; + eval $PRE_TEST_COMMANDS; + ./meteor self-test \ + "$TEST_GROUP" \ + --browserstack \ + --retries ${METEOR_SELF_TEST_RETRIES} \ + --exclude "${SELF_TEST_EXCLUDE}" \ + --headless \ + --junit ./tmp/results/junit/bs5.xml \ + --without-tag "custom-warehouse" + no_output_timeout: 40m + - run: + <<: *run_save_node_bin + - store_test_results: + path: ./tmp/results + - persist_to_workspace: + root: . + paths: ./tmp/results/junit + - store_artifacts: + path: ./tmp/results + - store_artifacts: + path: /tmp/core_dumps + - store_artifacts: + path: /tmp/memuse.txt + # Test the JSDoc declarations which live within this codebase against the # Meteor Docs (https://github.com/meteor/docs) repository, where they'll # eventually be consumed. This test aims to provide an early warning of @@ -803,6 +1008,21 @@ workflows: - Test Group 10: requires: - Get Ready + - Test Browserstack 1: + requires: + - Get Ready + - Test Browserstack 2: + requires: + - Get Ready + - Test Browserstack 3: + requires: + - Get Ready + - Test Browserstack 4: + requires: + - Get Ready + - Test Browserstack 5: + requires: + - Get Ready - Clean Up: requires: - Isolated Tests @@ -817,3 +1037,8 @@ workflows: - Test Group 8 - Test Group 9 - Test Group 10 + - Test Browserstack 1 + - Test Browserstack 2 + - Test Browserstack 3 + - Test Browserstack 4 + - Test Browserstack 5 diff --git a/.eslintignore b/.eslintignore index 50cced0770..5228e27ede 100644 --- a/.eslintignore +++ b/.eslintignore @@ -90,7 +90,7 @@ tools/isobuild/js-analyze.js tools/isobuild/linker.js tools/isobuild/linter-plugin.js tools/isobuild/meteor-npm.js -tools/isobuild/npm-discards.js +tools/isobuild/npm-discards.ts tools/isobuild/package-api.js tools/isobuild/package-source.js tools/isobuild/source-arch.js diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 1b0c3cebfc..4cf028179a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ - - - - - - diff --git a/examples/unfinished/coffeeless/client/coffeeless.less b/examples/unfinished/coffeeless/client/coffeeless.less deleted file mode 100644 index b7ff8589c9..0000000000 --- a/examples/unfinished/coffeeless/client/coffeeless.less +++ /dev/null @@ -1,12 +0,0 @@ -@red: #842210; - -h1 { - color: @red; -} - -img { - display: block; - position: absolute; - top: 0px; - right: 0px; -} diff --git a/examples/unfinished/coffeeless/model.coffee b/examples/unfinished/coffeeless/model.coffee deleted file mode 100644 index d1a4baf4db..0000000000 --- a/examples/unfinished/coffeeless/model.coffee +++ /dev/null @@ -1,4 +0,0 @@ -root = exports ? this # export Presses globally. -root.Presses = new Mongo.Collection 'presses' - -Meteor.publish 'presses' diff --git a/examples/unfinished/coffeeless/public/4201645142_ec2e3bb3f8_b.jpg b/examples/unfinished/coffeeless/public/4201645142_ec2e3bb3f8_b.jpg deleted file mode 100644 index 93043abd34..0000000000 Binary files a/examples/unfinished/coffeeless/public/4201645142_ec2e3bb3f8_b.jpg and /dev/null differ diff --git a/examples/unfinished/controls/.meteor/.gitignore b/examples/unfinished/controls/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/controls/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/controls/.meteor/packages b/examples/unfinished/controls/.meteor/packages deleted file mode 100644 index 0aed446952..0000000000 --- a/examples/unfinished/controls/.meteor/packages +++ /dev/null @@ -1,7 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -autopublish -standard-app-packages diff --git a/examples/unfinished/controls/.meteor/release b/examples/unfinished/controls/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/controls/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/controls/client/controls.js b/examples/unfinished/controls/client/controls.js deleted file mode 100644 index 19631ea426..0000000000 --- a/examples/unfinished/controls/client/controls.js +++ /dev/null @@ -1,43 +0,0 @@ -var SPEW = function(str) { - SPEW.lines.push(str); - // use counter to signal invalidation - Session.set("SPEW_V", (Session.get("SPEW_V") || 0)+1); -}; -SPEW.lines = []; - -Template.radios.events = { - 'change input': function(event) { - //SPEW("change "+event.target.value); - if (event.target.checked) { - Session.set("current_band", event.target.value); - } - } -}; - -Template.radios.current_band = function() { - return Session.get("current_band"); -}; - -Template.radios.band_checked = function(b) { - return Session.equals("current_band", b) ? - 'checked="checked"' : ''; -}; - -Template.checkboxes.events = { - 'change input': function(event) { - Session.set("dst", event.target.checked); - } -}; - -Template.checkboxes.dst_checked = function() { - return Session.get("dst") ? 'checked="checked"' : ''; -}; - -Template.checkboxes.dst = function() { - return Session.get("dst") ? 'Yes' : 'No'; -}; - -Template.spew.lines = function() { - Session.get("SPEW_V"); - return SPEW.lines; -}; diff --git a/examples/unfinished/controls/controls.css b/examples/unfinished/controls/controls.css deleted file mode 100644 index b6b4052b43..0000000000 --- a/examples/unfinished/controls/controls.css +++ /dev/null @@ -1 +0,0 @@ -/* CSS declarations go here */ diff --git a/examples/unfinished/controls/controls.html b/examples/unfinished/controls/controls.html deleted file mode 100644 index 28e87fd29a..0000000000 --- a/examples/unfinished/controls/controls.html +++ /dev/null @@ -1,35 +0,0 @@ - - controls - - - - {{> radios}} - {{> checkboxes}} - {{> spew}} - - - - - - - diff --git a/examples/unfinished/jsparse-docs/.meteor/.gitignore b/examples/unfinished/jsparse-docs/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/jsparse-docs/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/jsparse-docs/.meteor/packages b/examples/unfinished/jsparse-docs/.meteor/packages deleted file mode 100644 index 0aed446952..0000000000 --- a/examples/unfinished/jsparse-docs/.meteor/packages +++ /dev/null @@ -1,7 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -autopublish -standard-app-packages diff --git a/examples/unfinished/jsparse-docs/.meteor/release b/examples/unfinished/jsparse-docs/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/jsparse-docs/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/jsparse-docs/jsparse-docs.css b/examples/unfinished/jsparse-docs/jsparse-docs.css deleted file mode 100644 index a233a3ffb0..0000000000 --- a/examples/unfinished/jsparse-docs/jsparse-docs.css +++ /dev/null @@ -1,42 +0,0 @@ - -p, .topnotes .nodespec { margin: 0.8em; } -.topnotes { - background: #ffd; - margin-bottom: 2em; - margin-left: 1em; - margin-right: 1em; - border: 2px solid #ccc; -} - -.str { font-weight: bold; } -.token { font-family: monospace; font-size: 110%; font-weight: bold; } -.token, .tokentype { background: #ddd; padding: 2px 5px; } -.tokentype { font-size: 85%; } -.ref { font-style: italic; } -.punc { font-size: 140%; } -.comma { color: #fff; } -.or { padding-left: 3px; padding-right: 3px; } - -.nodespec { - font-size: 16px; - margin: 1em 0; - line-height: 20px; -} - -.indent { - margin-left: 2em; -} - -.explan { - margin-left: 20em; - margin-right: 2em; - border: 1px solid #ccc; -} - -#page { max-width: 50em; margin: 0 auto; } - -.spacer { text-align: center; font-size:50%; font-weight: bold; border-top: 1px solid #999; - margin-left: 6em; margin-right: 6em; - } - -code { font-weight: bold; } diff --git a/examples/unfinished/jsparse-docs/jsparse-docs.html b/examples/unfinished/jsparse-docs/jsparse-docs.html deleted file mode 100644 index 8be0c0e386..0000000000 --- a/examples/unfinished/jsparse-docs/jsparse-docs.html +++ /dev/null @@ -1,279 +0,0 @@ - - jsparse Docs - - - -
- {{> page}} -
- - - diff --git a/examples/unfinished/jsparse-docs/jsparse-docs.js b/examples/unfinished/jsparse-docs/jsparse-docs.js deleted file mode 100644 index 72b161df71..0000000000 --- a/examples/unfinished/jsparse-docs/jsparse-docs.js +++ /dev/null @@ -1,67 +0,0 @@ - - -if (Meteor.isClient) { - Template.page.nodespec = function (fn) { - var parts = [fn()]; - var replaceParts = function(regex, replacementFunc) { - var newParts = []; - _.each(parts, function (part) { - if (typeof part !== 'string') { - newParts.push(part); - return; - } - regex.lastIndex = 0; - var charsTaken = 0; - var matchResult; - while ((matchResult = regex.exec(part))) { - var matchIndex = matchResult.index; - if (matchIndex > charsTaken) - newParts.push(part.substring(charsTaken, matchIndex)); - charsTaken = regex.lastIndex; - var replacementParts = replacementFunc(matchResult); - newParts.push.apply(newParts, _.toArray(replacementParts)); - } - if (charsTaken < part.length) - newParts.push(part.slice(charsTaken)); - }); - parts = newParts; - }; - - parts.unshift(['
']); - parts.push(['
']); - replaceParts(/".*?"/g, function (match) { - return [['', Handlebars._escape(match[0]), '']]; - }); - replaceParts(/`(.*?)`/g, function (match) { - return [['', Handlebars._escape(match[1]), '']]; - }); - replaceParts(/[A-Z]{3,}/g, function (match) { - return [['', Handlebars._escape(match[0]), '']]; - }); - replaceParts(/[a-z]\w*/g, function (match) { - return [['', Handlebars._escape(match[0]), '']]; - }); - replaceParts(/[\[\]()|.,*?]/g, function (match) { - return [[''], match[0], ['']]; - }); - replaceParts(/,/g, function (match) { - return [[''], match[0], ['']]; - }); - replaceParts(/\|/g, function (match) { - return [[''], match[0], ['']]; - }); - - var html = _.map(parts, function (part) { - if (typeof part === "string") - return Handlebars._escape(part); - return part.join(''); - }).join(''); - - return new Handlebars.SafeString(html); - }; - - Template.page.spacer = function () { - return new Handlebars.SafeString('
 
'); - }; - -} diff --git a/examples/unfinished/leaderboard-remote/.meteor/.gitignore b/examples/unfinished/leaderboard-remote/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/leaderboard-remote/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/leaderboard-remote/.meteor/packages b/examples/unfinished/leaderboard-remote/.meteor/packages deleted file mode 100644 index 0aed446952..0000000000 --- a/examples/unfinished/leaderboard-remote/.meteor/packages +++ /dev/null @@ -1,7 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -autopublish -standard-app-packages diff --git a/examples/unfinished/leaderboard-remote/.meteor/release b/examples/unfinished/leaderboard-remote/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/leaderboard-remote/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.css b/examples/unfinished/leaderboard-remote/client/leaderboard-remote.css deleted file mode 100644 index 7f84876b6d..0000000000 --- a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.css +++ /dev/null @@ -1,41 +0,0 @@ -body { - width: 400px; - margin: 100px auto 0 auto; - background-color: white; - font-family: 'Helvetica Neue', Helvetica, Arial, san-serif; - line-height: 1.3; -} - -#meteor { - position: absolute; - left: 0px; - bottom: 0px; - opacity: .25; - z-index: -1; -} - -h1 { - color: red; - font-size: 3em; - font-weight: 200; - border-style: solid none none none; - border-color: red; - border-width: 4px; -} - -.button_demo { - margin-top: 2em; - width: 100%; -} - -.button_demo input { - display: block; - margin: 0 auto .5em auto; - width: 125px; -} - -.button_demo div { - text-align: center; - color: #777; - font-weight: bold; -} diff --git a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.html b/examples/unfinished/leaderboard-remote/client/leaderboard-remote.html deleted file mode 100644 index 903030c2db..0000000000 --- a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.html +++ /dev/null @@ -1,32 +0,0 @@ - - Remote collection demo - - - -
- - - {{> main}} - -
- - - diff --git a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.js b/examples/unfinished/leaderboard-remote/client/leaderboard-remote.js deleted file mode 100644 index ff1693759d..0000000000 --- a/examples/unfinished/leaderboard-remote/client/leaderboard-remote.js +++ /dev/null @@ -1,51 +0,0 @@ -Leaderboard = DDP.connect("http://leader2.meteor.com/sockjs"); - -// XXX I'd rather this be Leaderboard.Players.. can this API be easier? -Players = new Mongo.Collection("players", {manager: Leaderboard}); - -Template.main.events = { - 'keydown': function () { - Session.set("error", null); - }, - 'click .add': function () { - var name = $('#name').val(); - var score = $('#score').val(); - - if (name.match(/^\s*$/)) { - Session.set("error", "You must give a name"); - return; - } - if (score.match(/^\s*$/)) { - Session.set("error", "You must give a score"); - return; - } - score = +score; - if (isNaN(score)) { - Session.set("error", "Score must be a number"); - return; - } - - Players.insert({name: name, score: score}); - $('#name').val(''); - $('#score').val(''); - }, - 'click .take-points': function () { - var top = Players.findOne({}, {sort: {score: -1}}); - if (top) - Players.update(top._id, {$inc: {score: -20}}); - }, -}; - -Template.main.error = function () { - return Session.get("error"); -}; - -Template.main.average_score = function () { - var count = 0; - var total = 0; - Players.find().forEach(function (player) { - count++; - total += player.score; - }); - return total / count; -}; diff --git a/examples/unfinished/leaderboard-remote/public/planes.png b/examples/unfinished/leaderboard-remote/public/planes.png deleted file mode 100644 index 7c18d610be..0000000000 Binary files a/examples/unfinished/leaderboard-remote/public/planes.png and /dev/null differ diff --git a/examples/unfinished/movers/.meteor/.gitignore b/examples/unfinished/movers/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/movers/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/movers/.meteor/packages b/examples/unfinished/movers/.meteor/packages deleted file mode 100644 index 85521b15a9..0000000000 --- a/examples/unfinished/movers/.meteor/packages +++ /dev/null @@ -1,10 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -standard-app-packages -autopublish -insecure -preserve-inputs -less diff --git a/examples/unfinished/movers/.meteor/release b/examples/unfinished/movers/.meteor/release deleted file mode 100644 index 621e94f0ec..0000000000 --- a/examples/unfinished/movers/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -none diff --git a/examples/unfinished/movers/client/jquery-ui-sortable.js b/examples/unfinished/movers/client/jquery-ui-sortable.js deleted file mode 100755 index 0d85cfa365..0000000000 --- a/examples/unfinished/movers/client/jquery-ui-sortable.js +++ /dev/null @@ -1,2252 +0,0 @@ -/*! jQuery UI - v1.10.3 - 2013-07-30 -* http://jqueryui.com -* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js -* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ - -(function( $, undefined ) { - -var uuid = 0, - runiqueId = /^ui-id-\d+$/; - -// $.ui might exist from components with no dependencies, e.g., $.ui.position -$.ui = $.ui || {}; - -$.extend( $.ui, { - version: "1.10.3", - - keyCode: { - BACKSPACE: 8, - COMMA: 188, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - LEFT: 37, - NUMPAD_ADD: 107, - NUMPAD_DECIMAL: 110, - NUMPAD_DIVIDE: 111, - NUMPAD_ENTER: 108, - NUMPAD_MULTIPLY: 106, - NUMPAD_SUBTRACT: 109, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SPACE: 32, - TAB: 9, - UP: 38 - } -}); - -// plugins -$.fn.extend({ - focus: (function( orig ) { - return function( delay, fn ) { - return typeof delay === "number" ? - this.each(function() { - var elem = this; - setTimeout(function() { - $( elem ).focus(); - if ( fn ) { - fn.call( elem ); - } - }, delay ); - }) : - orig.apply( this, arguments ); - }; - })( $.fn.focus ), - - scrollParent: function() { - var scrollParent; - if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { - scrollParent = this.parents().filter(function() { - return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); - }).eq(0); - } else { - scrollParent = this.parents().filter(function() { - return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); - }).eq(0); - } - - return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; - }, - - zIndex: function( zIndex ) { - if ( zIndex !== undefined ) { - return this.css( "zIndex", zIndex ); - } - - if ( this.length ) { - var elem = $( this[ 0 ] ), position, value; - while ( elem.length && elem[ 0 ] !== document ) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned - position = elem.css( "position" ); - if ( position === "absolute" || position === "relative" || position === "fixed" ) { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - //
- value = parseInt( elem.css( "zIndex" ), 10 ); - if ( !isNaN( value ) && value !== 0 ) { - return value; - } - } - elem = elem.parent(); - } - } - - return 0; - }, - - uniqueId: function() { - return this.each(function() { - if ( !this.id ) { - this.id = "ui-id-" + (++uuid); - } - }); - }, - - removeUniqueId: function() { - return this.each(function() { - if ( runiqueId.test( this.id ) ) { - $( this ).removeAttr( "id" ); - } - }); - } -}); - -// selectors -function focusable( element, isTabIndexNotNaN ) { - var map, mapName, img, - nodeName = element.nodeName.toLowerCase(); - if ( "area" === nodeName ) { - map = element.parentNode; - mapName = map.name; - if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { - return false; - } - img = $( "img[usemap=#" + mapName + "]" )[0]; - return !!img && visible( img ); - } - return ( /input|select|textarea|button|object/.test( nodeName ) ? - !element.disabled : - "a" === nodeName ? - element.href || isTabIndexNotNaN : - isTabIndexNotNaN) && - // the element and all of its ancestors must be visible - visible( element ); -} - -function visible( element ) { - return $.expr.filters.visible( element ) && - !$( element ).parents().addBack().filter(function() { - return $.css( this, "visibility" ) === "hidden"; - }).length; -} - -$.extend( $.expr[ ":" ], { - data: $.expr.createPseudo ? - $.expr.createPseudo(function( dataName ) { - return function( elem ) { - return !!$.data( elem, dataName ); - }; - }) : - // support: jQuery <1.8 - function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - }, - - focusable: function( element ) { - return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); - }, - - tabbable: function( element ) { - var tabIndex = $.attr( element, "tabindex" ), - isTabIndexNaN = isNaN( tabIndex ); - return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); - } -}); - -// support: jQuery <1.8 -if ( !$( "" ).outerWidth( 1 ).jquery ) { - $.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; - - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; - if ( border ) { - size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; - } - if ( margin ) { - size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - - return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); - }); - }; - - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } - - return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); - }); - }; - }); -} - -// support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - -// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) -if ( $( "" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { - $.fn.removeData = (function( removeData ) { - return function( key ) { - if ( arguments.length ) { - return removeData.call( this, $.camelCase( key ) ); - } else { - return removeData.call( this ); - } - }; - })( $.fn.removeData ); -} - - - - - -// deprecated -$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); - -$.support.selectstart = "onselectstart" in document.createElement( "div" ); -$.fn.extend({ - disableSelection: function() { - return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + - ".ui-disableSelection", function( event ) { - event.preventDefault(); - }); - }, - - enableSelection: function() { - return this.unbind( ".ui-disableSelection" ); - } -}); - -$.extend( $.ui, { - // $.ui.plugin is deprecated. Use $.widget() extensions instead. - plugin: { - add: function( module, option, set ) { - var i, - proto = $.ui[ module ].prototype; - for ( i in set ) { - proto.plugins[ i ] = proto.plugins[ i ] || []; - proto.plugins[ i ].push( [ option, set[ i ] ] ); - } - }, - call: function( instance, name, args ) { - var i, - set = instance.plugins[ name ]; - if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { - return; - } - - for ( i = 0; i < set.length; i++ ) { - if ( instance.options[ set[ i ][ 0 ] ] ) { - set[ i ][ 1 ].apply( instance.element, args ); - } - } - } - }, - - // only used by resizable - hasScroll: function( el, a ) { - - //If overflow is hidden, the element might have extra content, but the user wants to hide it - if ( $( el ).css( "overflow" ) === "hidden") { - return false; - } - - var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", - has = false; - - if ( el[ scroll ] > 0 ) { - return true; - } - - // TODO: determine which cases actually cause this to happen - // if the element doesn't have the scroll set, see if it's possible to - // set the scroll - el[ scroll ] = 1; - has = ( el[ scroll ] > 0 ); - el[ scroll ] = 0; - return has; - } -}); - -})( jQuery ); -(function( $, undefined ) { - -var uuid = 0, - slice = Array.prototype.slice, - _cleanData = $.cleanData; -$.cleanData = function( elems ) { - for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { - try { - $( elem ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - _cleanData( elems ); -}; - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); -}; - -$.widget.extend = function( target ) { - var input = slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = slice.call( arguments, 1 ), - returnValue = this; - - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.widget.extend.apply( null, [ options ].concat(args) ) : - options; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} )._init(); - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - // 1.9 BC for #7810 - // TODO remove dual storage - .removeData( this.widgetName ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( value === undefined ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( value === undefined ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - - return this; - }, - - enable: function() { - return this._setOption( "disabled", false ); - }, - disable: function() { - return this._setOption( "disabled", true ); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - // accept selectors, DOM elements - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^(\w+)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -})( jQuery ); -(function( $, undefined ) { - -var mouseHandled = false; -$( document ).mouseup( function() { - mouseHandled = false; -}); - -$.widget("ui.mouse", { - version: "1.10.3", - options: { - cancel: "input,textarea,button,select,option", - distance: 1, - delay: 0 - }, - _mouseInit: function() { - var that = this; - - this.element - .bind("mousedown."+this.widgetName, function(event) { - return that._mouseDown(event); - }) - .bind("click."+this.widgetName, function(event) { - if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { - $.removeData(event.target, that.widgetName + ".preventClickEvent"); - event.stopImmediatePropagation(); - return false; - } - }); - - this.started = false; - }, - - // TODO: make sure destroying one instance of mouse doesn't mess with - // other instances of mouse - _mouseDestroy: function() { - this.element.unbind("."+this.widgetName); - if ( this._mouseMoveDelegate ) { - $(document) - .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); - } - }, - - _mouseDown: function(event) { - // don't let more than one widget handle mouseStart - if( mouseHandled ) { return; } - - // we may have missed mouseup (out of window) - (this._mouseStarted && this._mouseUp(event)); - - this._mouseDownEvent = event; - - var that = this, - btnIsLeft = (event.which === 1), - // event.target.nodeName works around a bug in IE 8 with - // disabled inputs (#7620) - elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { - return true; - } - - this.mouseDelayMet = !this.options.delay; - if (!this.mouseDelayMet) { - this._mouseDelayTimer = setTimeout(function() { - that.mouseDelayMet = true; - }, this.options.delay); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = (this._mouseStart(event) !== false); - if (!this._mouseStarted) { - event.preventDefault(); - return true; - } - } - - // Click event may never have fired (Gecko & Opera) - if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { - $.removeData(event.target, this.widgetName + ".preventClickEvent"); - } - - // these delegates are required to keep context - this._mouseMoveDelegate = function(event) { - return that._mouseMove(event); - }; - this._mouseUpDelegate = function(event) { - return that._mouseUp(event); - }; - $(document) - .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .bind("mouseup."+this.widgetName, this._mouseUpDelegate); - - event.preventDefault(); - - mouseHandled = true; - return true; - }, - - _mouseMove: function(event) { - // IE mouseup check - mouseup happened when mouse was out of window - if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { - return this._mouseUp(event); - } - - if (this._mouseStarted) { - this._mouseDrag(event); - return event.preventDefault(); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = - (this._mouseStart(this._mouseDownEvent, event) !== false); - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); - } - - return !this._mouseStarted; - }, - - _mouseUp: function(event) { - $(document) - .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); - - if (this._mouseStarted) { - this._mouseStarted = false; - - if (event.target === this._mouseDownEvent.target) { - $.data(event.target, this.widgetName + ".preventClickEvent", true); - } - - this._mouseStop(event); - } - - return false; - }, - - _mouseDistanceMet: function(event) { - return (Math.max( - Math.abs(this._mouseDownEvent.pageX - event.pageX), - Math.abs(this._mouseDownEvent.pageY - event.pageY) - ) >= this.options.distance - ); - }, - - _mouseDelayMet: function(/* event */) { - return this.mouseDelayMet; - }, - - // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(/* event */) {}, - _mouseDrag: function(/* event */) {}, - _mouseStop: function(/* event */) {}, - _mouseCapture: function(/* event */) { return true; } -}); - -})(jQuery); -(function( $, undefined ) { - -/*jshint loopfunc: true */ - -function isOverAxis( x, reference, size ) { - return ( x > reference ) && ( x < ( reference + size ) ); -} - -function isFloating(item) { - return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); -} - -$.widget("ui.sortable", $.ui.mouse, { - version: "1.10.3", - widgetEventPrefix: "sort", - ready: false, - options: { - appendTo: "parent", - axis: false, - connectWith: false, - containment: false, - cursor: "auto", - cursorAt: false, - dropOnEmpty: true, - forcePlaceholderSize: false, - forceHelperSize: false, - grid: false, - handle: false, - helper: "original", - items: "> *", - opacity: false, - placeholder: false, - revert: false, - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - scope: "default", - tolerance: "intersect", - zIndex: 1000, - - // callbacks - activate: null, - beforeStop: null, - change: null, - deactivate: null, - out: null, - over: null, - receive: null, - remove: null, - sort: null, - start: null, - stop: null, - update: null - }, - _create: function() { - - var o = this.options; - this.containerCache = {}; - this.element.addClass("ui-sortable"); - - //Get the items - this.refresh(); - - //Let's determine if the items are being displayed horizontally - this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; - - //Let's determine the parent's offset - this.offset = this.element.offset(); - - //Initialize mouse events for interaction - this._mouseInit(); - - //We're ready to go - this.ready = true; - - }, - - _destroy: function() { - this.element - .removeClass("ui-sortable ui-sortable-disabled"); - this._mouseDestroy(); - - for ( var i = this.items.length - 1; i >= 0; i-- ) { - this.items[i].item.removeData(this.widgetName + "-item"); - } - - return this; - }, - - _setOption: function(key, value){ - if ( key === "disabled" ) { - this.options[ key ] = value; - - this.widget().toggleClass( "ui-sortable-disabled", !!value ); - } else { - // Don't call widget base _setOption for disable as it adds ui-state-disabled class - $.Widget.prototype._setOption.apply(this, arguments); - } - }, - - _mouseCapture: function(event, overrideHandle) { - var currentItem = null, - validHandle = false, - that = this; - - if (this.reverting) { - return false; - } - - if(this.options.disabled || this.options.type === "static") { - return false; - } - - //We have to refresh the items data once first - this._refreshItems(event); - - //Find out if the clicked node (or one of its parents) is a actual item in this.items - $(event.target).parents().each(function() { - if($.data(this, that.widgetName + "-item") === that) { - currentItem = $(this); - return false; - } - }); - if($.data(event.target, that.widgetName + "-item") === that) { - currentItem = $(event.target); - } - - if(!currentItem) { - return false; - } - if(this.options.handle && !overrideHandle) { - $(this.options.handle, currentItem).find("*").addBack().each(function() { - if(this === event.target) { - validHandle = true; - } - }); - if(!validHandle) { - return false; - } - } - - this.currentItem = currentItem; - this._removeCurrentsFromItems(); - return true; - - }, - - _mouseStart: function(event, overrideHandle, noActivation) { - - var i, body, - o = this.options; - - this.currentContainer = this; - - //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture - this.refreshPositions(); - - //Create and append the visible helper - this.helper = this._createHelper(event); - - //Cache the helper size - this._cacheHelperProportions(); - - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ - - //Cache the margins of the original element - this._cacheMargins(); - - //Get the next scrolling parent - this.scrollParent = this.helper.scrollParent(); - - //The element's absolute position on the page minus margins - this.offset = this.currentItem.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; - - $.extend(this.offset, { - click: { //Where the click happened, relative to the element - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper - }); - - // Only after we got the offset, we can change the helper's position to absolute - // TODO: Still need to figure out a way to make relative sorting possible - this.helper.css("position", "absolute"); - this.cssPosition = this.helper.css("position"); - - //Generate the original position - this.originalPosition = this._generatePosition(event); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; - - //Adjust the mouse offset relative to the helper if "cursorAt" is supplied - (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); - - //Cache the former DOM position - this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; - - //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way - if(this.helper[0] !== this.currentItem[0]) { - this.currentItem.hide(); - } - - //Create the placeholder - this._createPlaceholder(); - - //Set a containment if given in the options - if(o.containment) { - this._setContainment(); - } - - if( o.cursor && o.cursor !== "auto" ) { // cursor option - body = this.document.find( "body" ); - - // support: IE - this.storedCursor = body.css( "cursor" ); - body.css( "cursor", o.cursor ); - - this.storedStylesheet = $( "" ).appendTo( body ); - } - - if(o.opacity) { // opacity option - if (this.helper.css("opacity")) { - this._storedOpacity = this.helper.css("opacity"); - } - this.helper.css("opacity", o.opacity); - } - - if(o.zIndex) { // zIndex option - if (this.helper.css("zIndex")) { - this._storedZIndex = this.helper.css("zIndex"); - } - this.helper.css("zIndex", o.zIndex); - } - - //Prepare scrolling - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { - this.overflowOffset = this.scrollParent.offset(); - } - - //Call callbacks - this._trigger("start", event, this._uiHash()); - - //Recache the helper size - if(!this._preserveHelperProportions) { - this._cacheHelperProportions(); - } - - - //Post "activate" events to possible containers - if( !noActivation ) { - for ( i = this.containers.length - 1; i >= 0; i-- ) { - this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); - } - } - - //Prepare possible droppables - if($.ui.ddmanager) { - $.ui.ddmanager.current = this; - } - - if ($.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - - this.dragging = true; - - this.helper.addClass("ui-sortable-helper"); - this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position - return true; - - }, - - _mouseDrag: function(event) { - var i, item, itemElement, intersection, - o = this.options, - scrolled = false; - - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); - - if (!this.lastPositionAbs) { - this.lastPositionAbs = this.positionAbs; - } - - //Do scrolling - if(this.options.scroll) { - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { - - if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; - } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; - } - - if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; - } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; - } - - } else { - - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); - } - - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); - } - - } - - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - } - - //Regenerate the absolute position used for position checks - this.positionAbs = this._convertPositionTo("absolute"); - - //Set the helper position - if(!this.options.axis || this.options.axis !== "y") { - this.helper[0].style.left = this.position.left+"px"; - } - if(!this.options.axis || this.options.axis !== "x") { - this.helper[0].style.top = this.position.top+"px"; - } - - //Rearrange - for (i = this.items.length - 1; i >= 0; i--) { - - //Cache variables and intersection, continue if no intersection - item = this.items[i]; - itemElement = item.item[0]; - intersection = this._intersectsWithPointer(item); - if (!intersection) { - continue; - } - - // Only put the placeholder inside the current Container, skip all - // items form other containers. This works because when moving - // an item from one container to another the - // currentContainer is switched before the placeholder is moved. - // - // Without this moving items in "sub-sortables" can cause the placeholder to jitter - // beetween the outer and inner container. - if (item.instance !== this.currentContainer) { - continue; - } - - // cannot intersect with itself - // no useless actions that have been done before - // no action if the item moved is the parent of the item checked - if (itemElement !== this.currentItem[0] && - this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && - !$.contains(this.placeholder[0], itemElement) && - (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) - ) { - - this.direction = intersection === 1 ? "down" : "up"; - - if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { - this._rearrange(event, item); - } else { - break; - } - - this._trigger("change", event, this._uiHash()); - break; - } - } - - //Post events to containers - this._contactContainers(event); - - //Interconnect with droppables - if($.ui.ddmanager) { - $.ui.ddmanager.drag(this, event); - } - - //Call callbacks - this._trigger("sort", event, this._uiHash()); - - this.lastPositionAbs = this.positionAbs; - return false; - - }, - - _mouseStop: function(event, noPropagation) { - - if(!event) { - return; - } - - //If we are using droppables, inform the manager about the drop - if ($.ui.ddmanager && !this.options.dropBehaviour) { - $.ui.ddmanager.drop(this, event); - } - - if(this.options.revert) { - var that = this, - cur = this.placeholder.offset(), - axis = this.options.axis, - animation = {}; - - if ( !axis || axis === "x" ) { - animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); - } - if ( !axis || axis === "y" ) { - animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); - } - this.reverting = true; - $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { - that._clear(event); - }); - } else { - this._clear(event, noPropagation); - } - - return false; - - }, - - cancel: function() { - - if(this.dragging) { - - this._mouseUp({ target: null }); - - if(this.options.helper === "original") { - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - //Post deactivating events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - this.containers[i]._trigger("deactivate", null, this._uiHash(this)); - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", null, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - if (this.placeholder) { - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - if(this.placeholder[0].parentNode) { - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - } - if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { - this.helper.remove(); - } - - $.extend(this, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); - - if(this.domPosition.prev) { - $(this.domPosition.prev).after(this.currentItem); - } else { - $(this.domPosition.parent).prepend(this.currentItem); - } - } - - return this; - - }, - - serialize: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - str = []; - o = o || {}; - - $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); - if (res) { - str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); - } - }); - - if(!str.length && o.key) { - str.push(o.key + "="); - } - - return str.join("&"); - - }, - - toArray: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - ret = []; - - o = o || {}; - - items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); - return ret; - - }, - - /* Be careful with the following core functions */ - _intersectsWith: function(item) { - - var x1 = this.positionAbs.left, - x2 = x1 + this.helperProportions.width, - y1 = this.positionAbs.top, - y2 = y1 + this.helperProportions.height, - l = item.left, - r = l + item.width, - t = item.top, - b = t + item.height, - dyClick = this.offset.click.top, - dxClick = this.offset.click.left, - isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), - isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), - isOverElement = isOverElementHeight && isOverElementWidth; - - if ( this.options.tolerance === "pointer" || - this.options.forcePointerForContainers || - (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) - ) { - return isOverElement; - } else { - - return (l < x1 + (this.helperProportions.width / 2) && // Right Half - x2 - (this.helperProportions.width / 2) < r && // Left Half - t < y1 + (this.helperProportions.height / 2) && // Bottom Half - y2 - (this.helperProportions.height / 2) < b ); // Top Half - - } - }, - - _intersectsWithPointer: function(item) { - - var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), - isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), - isOverElement = isOverElementHeight && isOverElementWidth, - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (!isOverElement) { - return false; - } - - return this.floating ? - ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) - : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); - - }, - - _intersectsWithSides: function(item) { - - var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), - isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (this.floating && horizontalDirection) { - return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); - } else { - return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); - } - - }, - - _getDragVerticalDirection: function() { - var delta = this.positionAbs.top - this.lastPositionAbs.top; - return delta !== 0 && (delta > 0 ? "down" : "up"); - }, - - _getDragHorizontalDirection: function() { - var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta !== 0 && (delta > 0 ? "right" : "left"); - }, - - refresh: function(event) { - this._refreshItems(event); - this.refreshPositions(); - return this; - }, - - _connectWith: function() { - var options = this.options; - return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; - }, - - _getItemsAsjQuery: function(connected) { - - var i, j, cur, inst, - items = [], - queries = [], - connectWith = this._connectWith(); - - if(connectWith && connected) { - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); - for ( j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); - } - } - } - } - - queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); - - for (i = queries.length - 1; i >= 0; i--){ - queries[i][0].each(function() { - items.push(this); - }); - } - - return $(items); - - }, - - _removeCurrentsFromItems: function() { - - var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); - - this.items = $.grep(this.items, function (item) { - for (var j=0; j < list.length; j++) { - if(list[j] === item.item[0]) { - return false; - } - } - return true; - }); - - }, - - _refreshItems: function(event) { - - this.items = []; - this.containers = [this]; - - var i, j, cur, inst, targetData, _queries, item, queriesLength, - items = this.items, - queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], - connectWith = this._connectWith(); - - if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); - for (j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); - this.containers.push(inst); - } - } - } - } - - for (i = queries.length - 1; i >= 0; i--) { - targetData = queries[i][1]; - _queries = queries[i][0]; - - for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { - item = $(_queries[j]); - - item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) - - items.push({ - item: item, - instance: targetData, - width: 0, height: 0, - left: 0, top: 0 - }); - } - } - - }, - - refreshPositions: function(fast) { - - //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change - if(this.offsetParent && this.helper) { - this.offset.parent = this._getParentOffset(); - } - - var i, item, t, p; - - for (i = this.items.length - 1; i >= 0; i--){ - item = this.items[i]; - - //We ignore calculating positions of all connected containers when we're not over them - if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { - continue; - } - - t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; - - if (!fast) { - item.width = t.outerWidth(); - item.height = t.outerHeight(); - } - - p = t.offset(); - item.left = p.left; - item.top = p.top; - } - - if(this.options.custom && this.options.custom.refreshContainers) { - this.options.custom.refreshContainers.call(this); - } else { - for (i = this.containers.length - 1; i >= 0; i--){ - p = this.containers[i].element.offset(); - this.containers[i].containerCache.left = p.left; - this.containers[i].containerCache.top = p.top; - this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); - this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); - } - } - - return this; - }, - - _createPlaceholder: function(that) { - that = that || this; - var className, - o = that.options; - - if(!o.placeholder || o.placeholder.constructor === String) { - className = o.placeholder; - o.placeholder = { - element: function() { - - var nodeName = that.currentItem[0].nodeName.toLowerCase(), - element = $( "<" + nodeName + ">", that.document[0] ) - .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") - .removeClass("ui-sortable-helper"); - - if ( nodeName === "tr" ) { - that.currentItem.children().each(function() { - $( " ", that.document[0] ) - .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) - .appendTo( element ); - }); - } else if ( nodeName === "img" ) { - element.attr( "src", that.currentItem.attr( "src" ) ); - } - - if ( !className ) { - element.css( "visibility", "hidden" ); - } - - return element; - }, - update: function(container, p) { - - // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that - // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified - if(className && !o.forcePlaceholderSize) { - return; - } - - //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item - if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } - if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } - } - }; - } - - //Create the placeholder - that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); - - //Append it after the actual current item - that.currentItem.after(that.placeholder); - - //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) - o.placeholder.update(that, that.placeholder); - - }, - - _contactContainers: function(event) { - var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, - innermostContainer = null, - innermostIndex = null; - - // get innermost container that intersects with item - for (i = this.containers.length - 1; i >= 0; i--) { - - // never consider a container that's located within the item itself - if($.contains(this.currentItem[0], this.containers[i].element[0])) { - continue; - } - - if(this._intersectsWith(this.containers[i].containerCache)) { - - // if we've already found a container and it's more "inner" than this, then continue - if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { - continue; - } - - innermostContainer = this.containers[i]; - innermostIndex = i; - - } else { - // container doesn't intersect. trigger "out" event if necessary - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", event, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - // if no intersecting containers found, return - if(!innermostContainer) { - return; - } - - // move the item into the container if it's not there already - if(this.containers.length === 1) { - if (!this.containers[innermostIndex].containerCache.over) { - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - } else { - - //When entering a new container, we will find the item with the least distance and append our item near it - dist = 10000; - itemWithLeastDistance = null; - floating = innermostContainer.floating || isFloating(this.currentItem); - posProperty = floating ? "left" : "top"; - sizeProperty = floating ? "width" : "height"; - base = this.positionAbs[posProperty] + this.offset.click[posProperty]; - for (j = this.items.length - 1; j >= 0; j--) { - if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { - continue; - } - if(this.items[j].item[0] === this.currentItem[0]) { - continue; - } - if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { - continue; - } - cur = this.items[j].item.offset()[posProperty]; - nearBottom = false; - if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ - nearBottom = true; - cur += this.items[j][sizeProperty]; - } - - if(Math.abs(cur - base) < dist) { - dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; - this.direction = nearBottom ? "up": "down"; - } - } - - //Check if dropOnEmpty is enabled - if(!itemWithLeastDistance && !this.options.dropOnEmpty) { - return; - } - - if(this.currentContainer === this.containers[innermostIndex]) { - return; - } - - itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); - this._trigger("change", event, this._uiHash()); - this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - this.currentContainer = this.containers[innermostIndex]; - - //Update the placeholder - this.options.placeholder.update(this.currentContainer, this.placeholder); - - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - - - }, - - _createHelper: function(event) { - - var o = this.options, - helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); - - //Add the helper to the DOM if that didn't happen already - if(!helper.parents("body").length) { - $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); - } - - if(helper[0] === this.currentItem[0]) { - this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; - } - - if(!helper[0].style.width || o.forceHelperSize) { - helper.width(this.currentItem.width()); - } - if(!helper[0].style.height || o.forceHelperSize) { - helper.height(this.currentItem.height()); - } - - return helper; - - }, - - _adjustOffsetFromHelper: function(obj) { - if (typeof obj === "string") { - obj = obj.split(" "); - } - if ($.isArray(obj)) { - obj = {left: +obj[0], top: +obj[1] || 0}; - } - if ("left" in obj) { - this.offset.click.left = obj.left + this.margins.left; - } - if ("right" in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - } - if ("top" in obj) { - this.offset.click.top = obj.top + this.margins.top; - } - if ("bottom" in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - } - }, - - _getParentOffset: function() { - - - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); - - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } - - // This needs to be actually done for all browsers, since pageX/pageY includes this information - // with an ugly IE fix - if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { - po = { top: 0, left: 0 }; - } - - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; - - }, - - _getRelativeOffset: function() { - - if(this.cssPosition === "relative") { - var p = this.currentItem.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; - } - - }, - - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), - top: (parseInt(this.currentItem.css("marginTop"),10) || 0) - }; - }, - - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, - - _setContainment: function() { - - var ce, co, over, - o = this.options; - if(o.containment === "parent") { - o.containment = this.helper[0].parentNode; - } - if(o.containment === "document" || o.containment === "window") { - this.containment = [ - 0 - this.offset.relative.left - this.offset.parent.left, - 0 - this.offset.relative.top - this.offset.parent.top, - $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, - ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; - } - - if(!(/^(document|window|parent)$/).test(o.containment)) { - ce = $(o.containment)[0]; - co = $(o.containment).offset(); - over = ($(ce).css("overflow") !== "hidden"); - - this.containment = [ - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, - co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, - co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - ]; - } - - }, - - _convertPositionTo: function(d, pos) { - - if(!pos) { - pos = this.position; - } - var mod = d === "absolute" ? 1 : -1, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, - scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - return { - top: ( - pos.top + // The absolute mouse position - this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left + // The absolute mouse position - this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; - - }, - - _generatePosition: function(event) { - - var top, left, - o = this.options, - pageX = event.pageX, - pageY = event.pageY, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - // This is another very weird special case that only happens for relative elements: - // 1. If the css position is relative - // 2. and the scroll parent is the document or similar to the offset parent - // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { - this.offset.relative = this._getRelativeOffset(); - } - - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ - - if(this.originalPosition) { //If we are not dragging yet, we won't check for options - - if(this.containment) { - if(event.pageX - this.offset.click.left < this.containment[0]) { - pageX = this.containment[0] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top < this.containment[1]) { - pageY = this.containment[1] + this.offset.click.top; - } - if(event.pageX - this.offset.click.left > this.containment[2]) { - pageX = this.containment[2] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top > this.containment[3]) { - pageY = this.containment[3] + this.offset.click.top; - } - } - - if(o.grid) { - top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } - - } - - return { - top: ( - pageY - // The absolute mouse position - this.offset.click.top - // Click offset (relative to the element) - this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX - // The absolute mouse position - this.offset.click.left - // Click offset (relative to the element) - this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - - }, - - _rearrange: function(event, i, a, hardRefresh) { - - a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); - - //Various things done here to improve the performance: - // 1. we create a setTimeout, that calls refreshPositions - // 2. on the instance, we have a counter variable, that get's higher after every append - // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same - // 4. this lets only the last addition to the timeout stack through - this.counter = this.counter ? ++this.counter : 1; - var counter = this.counter; - - this._delay(function() { - if(counter === this.counter) { - this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove - } - }); - - }, - - _clear: function(event, noPropagation) { - - this.reverting = false; - // We delay all events that have to be triggered to after the point where the placeholder has been removed and - // everything else normalized again - var i, - delayedTriggers = []; - - // We first have to update the dom position of the actual currentItem - // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) - if(!this._noFinalSort && this.currentItem.parent().length) { - this.placeholder.before(this.currentItem); - } - this._noFinalSort = null; - - if(this.helper[0] === this.currentItem[0]) { - for(i in this._storedCSS) { - if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { - this._storedCSS[i] = ""; - } - } - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - if(this.fromOutside && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); - } - if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed - } - - // Check if the items Container has Changed and trigger appropriate - // events. - if (this !== this.currentContainer) { - if(!noPropagation) { - delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); - delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - } - } - - - //Post events to containers - for (i = this.containers.length - 1; i >= 0; i--){ - if(!noPropagation) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - } - if(this.containers[i].containerCache.over) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - this.containers[i].containerCache.over = 0; - } - } - - //Do what was originally in plugins - if ( this.storedCursor ) { - this.document.find( "body" ).css( "cursor", this.storedCursor ); - this.storedStylesheet.remove(); - } - if(this._storedOpacity) { - this.helper.css("opacity", this._storedOpacity); - } - if(this._storedZIndex) { - this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); - } - - this.dragging = false; - if(this.cancelHelperRemoval) { - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - for (i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return false; - } - - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - } - - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - - if(this.helper[0] !== this.currentItem[0]) { - this.helper.remove(); - } - this.helper = null; - - if(!noPropagation) { - for (i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return true; - - }, - - _trigger: function() { - if ($.Widget.prototype._trigger.apply(this, arguments) === false) { - this.cancel(); - } - }, - - _uiHash: function(_inst) { - var inst = _inst || this; - return { - helper: inst.helper, - placeholder: inst.placeholder || $([]), - position: inst.position, - originalPosition: inst.originalPosition, - offset: inst.positionAbs, - item: inst.currentItem, - sender: _inst ? _inst.element : null - }; - } - -}); - -})(jQuery); diff --git a/examples/unfinished/movers/movers.html b/examples/unfinished/movers/movers.html deleted file mode 100644 index 08efb197ec..0000000000 --- a/examples/unfinished/movers/movers.html +++ /dev/null @@ -1,16 +0,0 @@ - - movers - - - - {{> main}} - - - diff --git a/examples/unfinished/movers/movers.js b/examples/unfinished/movers/movers.js deleted file mode 100644 index 8fe890660e..0000000000 --- a/examples/unfinished/movers/movers.js +++ /dev/null @@ -1,92 +0,0 @@ -if (Meteor.isClient) { - var moveCount = 0; - var MOVE_INTERVAL = 3000; - var MOVE_DURATION = 2000; - - doMove = function () { - moveCount++; - if (moveCount % 2 === 1) { - animateToBefore($('.green'), $('.yellow')); - animateToBefore($('.red'), null); - animateToBefore($('.blue'), null); - } else { - animateToBefore($('.red'), null); - animateToBefore($('.green'), null); - animateToBefore($('.blue'), null); - animateToBefore($('.yellow'), null); - } - }; - - Meteor.startup(function () { - doMove(); - window.setInterval(doMove, MOVE_INTERVAL); - }); - - - animateToBefore = function ($n, $newNext) { - // we don't use jQuery's `.css()` for these because we want the - // element's own style, not the computed style - var oldTop = $n[0].style.top; - var oldPosition = $n[0].style.position; - var oldZIndex = $n[0].style.zIndex; - var oldMarginBottom = $n[0].style.marginBottom; - - var outerHeight = $n.outerHeight(); // not margin - var marginBottom = parseInt($n.css('margin-bottom')); - - // TODO: test interesting elements like table rows, etc. - var placeholder = $(document.createElement($n[0].nodeName)); - var placeholderHeight = outerHeight + marginBottom; - placeholder.css('height', placeholderHeight); - // insert placeholder - $n.before(placeholder); - - // move node - if ($newNext) - $newNext.before($n); - else - $n.parent().append($n); - - // XXX would tracking "left" as well as "top" magically get us - // horizontal re-ordering? - $n.css({marginBottom: -outerHeight, - position: 'relative', - zIndex: 2, - top: 0}); - var vOffset = placeholder.offset().top - $n.offset().top; - $n.css('top', vOffset); - - $({t:0}).animate({t:1}, { - duration: MOVE_DURATION, - step: function (t, fx) { - var curPlaceholderHeight = Math.round(placeholderHeight * (1-t)); - var curMarginBottom = marginBottom - curPlaceholderHeight; - var curTop = (-curPlaceholderHeight + - Math.round((1-t) * (vOffset + placeholderHeight))); - $n.css({marginBottom: curMarginBottom, - top: curTop}); - placeholder.css('height', curPlaceholderHeight); - }, - progress: function (a, t) { - // if (t >= 0.5) { - // console.log(a); - // a.stop(); - // } - }, - complete: function () { - placeholder.remove(); - $n[0].style.top = oldTop; - $n[0].style.position = oldPosition; - $n[0].style.zIndex = oldZIndex; - $n[0].style.marginBottom = oldMarginBottom; - } - }); - }; - -} - -if (Meteor.isServer) { - Meteor.startup(function () { - // code to run on server at startup - }); -} diff --git a/examples/unfinished/movers/movers.less b/examples/unfinished/movers/movers.less deleted file mode 100644 index 0b08028c37..0000000000 --- a/examples/unfinished/movers/movers.less +++ /dev/null @@ -1,12 +0,0 @@ -.item { - border: 1px solid black; - padding: 10px; - font-size: 18px; - margin-bottom: 10px; - font-weight: bold; - position: relative; -} -.red { background: #fcc; } -.blue { background: #ccf; } -.green { background: #cfc; } -.yellow { background: #ffc; } diff --git a/examples/unfinished/parse-inspector/.meteor/.gitignore b/examples/unfinished/parse-inspector/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/parse-inspector/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/parse-inspector/.meteor/packages b/examples/unfinished/parse-inspector/.meteor/packages deleted file mode 100644 index 1d7becdbfe..0000000000 --- a/examples/unfinished/parse-inspector/.meteor/packages +++ /dev/null @@ -1,9 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -autopublish -preserve-inputs -jsparse -standard-app-packages diff --git a/examples/unfinished/parse-inspector/.meteor/release b/examples/unfinished/parse-inspector/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/parse-inspector/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/parse-inspector/parse-inspector.css b/examples/unfinished/parse-inspector/parse-inspector.css deleted file mode 100644 index f0c71202e7..0000000000 --- a/examples/unfinished/parse-inspector/parse-inspector.css +++ /dev/null @@ -1,191 +0,0 @@ - -* { padding: 0; margin: 0; } -html, body { height: 100%; } - -#topbar { - position: absolute; - width: 100%; - top: 0; - height: 39px; - border-bottom: 1px solid #555; - overflow: auto; - background: #cfc; - font-size: 12px; -} - -#topbarinner { - padding: 7px; - font-family: sans-serif; -} - -#main { - position: absolute; - width: 100%; - top: 40px; - bottom: 0; -} - -#inputarea { - border: 0; - border-right: 1px solid #555; - position: absolute; - height: 100%; - left: 0; - right: 50%; -} - -#inputarea textarea { - position: absolute; - width: 100%; - height: 100%; - font-family: monospace; - font-size: 100%; - border: 0; -} - -#outputoptions { - position: absolute; - left: 50%; - right: 0; - overflow: visible; - bottom: 0; - height: 29px; - border-top: 1px solid #555; - - background: #ccc; -} - -#output { - position: absolute; - left: 50%; - right: 0; - overflow: auto; - top: 0; - bottom: 30px; - - font-family: monospace; -} - -#outputoptions .output-type { - text-decoration: none; - font-family: sans-serif; - font-size: 14px; - display: inline-block; - background: #e2e2e2; - vertical-align: top; - position: relative; - top: -1px; - padding: 3px 8px; - margin-left: 6px; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - border: 1px solid #777; - border-top: 1px solid #555; - cursor: pointer; -} - -#outputoptions .output-type.selected { - font-weight: bold; - background: #fff; - border-top: 1px solid #fff; -} - -#inputarea textarea, #output { - line-height: 130%; -} - -.lex { border: 1px solid #333; cursor: pointer; } - -.lex_keyword { background: #0f0; } -.lex_identifier { background: #ff0; } -.lex_punctuation { background: #0ff; } -.lex_error { background: #f00; } -.lex_whitespace, .lex_newline, .lex_eof { background: #fcc; } -.lex_comment { background: #ccc; } - -.lex_regex { background: #f0f; } -.lex_null { background: #dac; } -.lex_boolean { background: #faf; } -.lex_number { background: #c3f; } -.lex_string { background: #fc3; } - -.parseerror { - background: #f99; - border: 1px solid blue; - cursor: pointer; -} -.parseerrormessage { color: #c00; } - -.box { - display: inline-block; - margin: 5px; - margin-top: 0; - background: #fff; -} - -.box.statement { - display: block; -} - -#output > .box { - margin-top: 5px; -} - -.box.named { - border: 1px solid #888; - border-radius: 5px; - cursor: pointer; - overflow: hidden; - /* position:relative breaks overflow:hidden effect of rounded corners? */ - position: static; -} - -.box.head { - font-family: sans-serif; - font-size: 70%; - font-weight: bold; - display: block; - margin-left: 0; - margin-right: 0; - background: #ccc; - color: #000; - padding-left: 5px; - padding-right: 5px; - border-bottom: 1px solid #888; -} - -.box.head:last-child { - margin: 0; - border-bottom: 0; -} - -.box.token { - background: #ddd; - /*border: 1px solid #999;*/ - border: 1px solid #00f; - cursor: pointer; - font-family: monospace; - font-weight: bold; - font-size: 120%; - padding: 1px; -} - -.box.named[mousehover] { - background: #cdf; - border: 1px solid #448; -} - -.box.token[mousehover] { - background: #ace; - border: 1px solid #448; -} - -.box.named[mousehover] > .box.head { - background: #58b; - border-bottom: 1px solid #448; -} - -.box.named[mousehover] > .box.head:last-child { - border-bottom: 0; -} - diff --git a/examples/unfinished/parse-inspector/parse-inspector.html b/examples/unfinished/parse-inspector/parse-inspector.html deleted file mode 100644 index ab3d3b36f6..0000000000 --- a/examples/unfinished/parse-inspector/parse-inspector.html +++ /dev/null @@ -1,34 +0,0 @@ - - jsparser - - - - {{> page}} - - - diff --git a/examples/unfinished/parse-inspector/parse-inspector.js b/examples/unfinished/parse-inspector/parse-inspector.js deleted file mode 100644 index d33a108de1..0000000000 --- a/examples/unfinished/parse-inspector/parse-inspector.js +++ /dev/null @@ -1,181 +0,0 @@ - - -if (Meteor.isClient) { - Meteor.startup(function () { - if (! Session.get("input")) - Session.set("input", "var x = 3"); - if (! Session.get("output-type")) - Session.set("output-type", "jsparse"); - }); - - Template.page.input = function () { - return Session.get("input") || ''; - }; - - Template.page.output = function () { - var input = Session.get("input") || ""; - - var outputType = Session.get("output-type"); - - if (outputType === "jslex") { - // LEXER - - var lexer = new JSLexer(input); - var html = ""; - var L; - do { - L = lexer.next(); - var content; - if (L.type() === "NEWLINE") { - content = ' 
'; - } else if (L.type() === "EOF") { - content = Handlebars._escape(""); - } else { - content = Handlebars._escape(L.text() || ' '); - content = content.replace(/(?!.)\s/g, '
'); // for multiline comments - content = content.replace(/\s/g, ' '); - } - html += Spark.setDataContext( - L, - '' + - content + ''); - } while (! L.isError() && ! L.isEOF()); - return new Handlebars.SafeString(html); - - } else if (outputType === "jsparse") { - - // PARSER - var html; - var tree = null; - var parser = new JSParser(input, {includeComments: true}); - try { - tree = parser.getSyntaxTree(); - } catch (parseError) { - var errorLexeme = parser.lexer.lastLexeme; - - html = Handlebars._escape( - input.substring(0, errorLexeme.startPos())); - html += Spark.setDataContext( - errorLexeme, - '' + - Handlebars._escape(errorLexeme.text() || '') + - ''); - html = html.replace(/(?!.)\s/g, '
'); - html += '
' + - Handlebars._escape(parseError.toString()) + '
'; - } - if (tree) { - var curPos = 0; - var unclosedInfos = []; - var toHtml = function (obj) { - if (obj instanceof ParseNode) { - var head = obj.name || ''; - var children = obj.children; - var info = { startPos: curPos }; - var isStatement = (head.indexOf('Stmnt') >= 0 || - head === "comment" || - head === "functionDecl"); - var html = Spark.setDataContext( - info, - '
' + Handlebars._escape(head) + '
' + - _.map(children, toHtml).join('') + '
'); - unclosedInfos.push(info); - return html; - } else if (obj.text) { - // token - _.each(unclosedInfos, function (info) { - info.endPos = curPos; - }); - curPos = obj.endPos(); - unclosedInfos.length = 0; - var text = obj.text(); - // insert zero-width spaces to allow wrapping - text = text.replace(/.{20}/g, "$&\u200b"); - text = Handlebars._escape(text); - text = text.replace(/\u200b/g, '​'); - text = text.replace(/\n/g, '
'); - return Spark.setDataContext( - obj, - '
' + text + '
'); - } else { - // other? - return '
' + - Handlebars._escape(JSON.stringify(obj)) + '
'; - } - }; - html = toHtml(tree); - curPos = parser.lexer.pos; - _.each(unclosedInfos, function (info) { - info.endPos = curPos; - }); - } - - return new Handlebars.SafeString(html); - } - else return ''; // unknown output tab? - }; - - Template.page.events({ - 'keyup #inputarea textarea': function (event) { - var input = event.currentTarget.value; - Session.set("input", input); - }, - 'mouseover .box.named, mouseover .box.token': function (event) { - event.currentTarget.setAttribute('mousehover', 'mousehover'); - event.stopImmediatePropagation(); - }, - 'mouseout .box.named, mouseout .box.token': function (event) { - event.currentTarget.removeAttribute('mousehover'); - event.stopImmediatePropagation(); - }, - 'click .box.token': function (event) { - selectInputText(this.startPos(), this.endPos()); - return false; - }, - 'click .box.named': function (event) { - selectInputText(this.startPos, this.endPos); - return false; - }, - 'click .parseerror': function (event) { - selectInputText(this.startPos(), this.endPos()); - return false; - }, - 'click .output-type': function (event) { - Session.set("output-type", this.value); - }, - 'click .lex': function (event) { - selectInputText(this.startPos(), this.endPos()); - return false; - } - }); - - Template.page.outputTypes = [ - {name: "JS Lex", value: "jslex"}, - {name: "JS Parse", value: "jsparse"} - ]; - - Template.page.is_outputtype_selected = function (which) { - return Session.equals("output-type", which) ? "selected" : ""; - }; - - var selectTextInArea = function (e, start, end){ - e.focus(); - if (e.setSelectionRange) { - e.setSelectionRange(start, end); - } else if (e.createTextRange) { - var r = e.createTextRange(); - r.collapse(true); - r.moveEnd('character', end); - r.moveStart('character', start); - r.select(); - } - }; - - var selectInputText = function (start, end) { - var textarea = DomUtils.find(document, '#inputarea textarea'); - selectTextInArea(textarea, start, end); - }; - -} diff --git a/examples/unfinished/python-ddp-client/README b/examples/unfinished/python-ddp-client/README deleted file mode 100644 index 44071bac3b..0000000000 --- a/examples/unfinished/python-ddp-client/README +++ /dev/null @@ -1 +0,0 @@ -sudo easy_install ws4py diff --git a/examples/unfinished/python-ddp-client/ddp-client.py b/examples/unfinished/python-ddp-client/ddp-client.py deleted file mode 100755 index 7300b3ae9b..0000000000 --- a/examples/unfinished/python-ddp-client/ddp-client.py +++ /dev/null @@ -1,306 +0,0 @@ -#!/usr/bin/env python2.7 - -import sys -import json -import time -import argparse -import thread -import threading -import traceback - -from ws4py.client.threadedclient import WebSocketClient -from cmd import Cmd - - -DDP_VERSIONS = ["pre1"] - -def log(msg): - """A shortcut to write to the standard error file descriptor""" - sys.stderr.write('{}\n'.format(msg)) - - -def parse_command(params): - """Parses a command with a first string param and a second - json-encoded param""" - name, args = (params + ' ').split(' ', 1) - return name, args and json.loads(args) or [] - - -class DDPClient(WebSocketClient): - """simple wrapper around Websockets for DDP connections""" - def __init__(self, url, print_raw): - WebSocketClient.__init__(self, url) - self.print_raw = print_raw - - # We keep track of methods and subs that have been sent from the - # client so that we only return to the prompt or quit the app - # once we get back all the results from the server. - # - # `id` - # - # The operation id, informed by the client and returned by the - # server to make sure both are talking about the same thing. - # - # `result_acked` - # - # Flag to make sure we were answered. - # - # `data_acked` - # - # Flag to make sure we received the correct data from the - # message we were waiting for. - self.pending_condition = threading.Condition() - self.pending = {} - - - def send(self, msg_dict): - """Send a message through the websocket client and wait for the - answer if the message being sent contains an id attribute. - - Also prints to the standard error fd. - - (NOTE: DDP does not require waiting for an answer but this is - a simple proof-of-concept client)""" - message = json.dumps(msg_dict) - if self.print_raw: - log('[RAW] >> {}'.format(message)) - super(DDPClient, self).send(message) - - # We don't need to wait for certain messages, just for the ones - # with ids. - if 'id' in msg_dict: - self.block_until_return(msg_dict['msg'], msg_dict['id']) - - def block_until_return(self, msg_type, msg_id): - """Wait until the msg_id that was sent to the server is answered""" - with self.pending_condition: - self.pending = {'id': msg_id} - - while self.pending.get('id') is not None: - if msg_type == 'method': - # Methods must validate both data and result flag - we_are_good = all(( - self.pending.get('result_acked'), - self.pending.get('data_acked'))) - else: - # Subs just need to validate data flag - we_are_good = self.pending.get('data_acked') - - if we_are_good: - return - self.pending_condition.wait() - - def opened(self): - """Set the connecte flag to true and send the connect message to - the server.""" - self.send({"msg": "connect", "version": DDP_VERSIONS[0], - "support": DDP_VERSIONS}) - - def received_message(self, data): - """Parse an incoming message and print it. Also update - self.pending appropriately""" - if self.print_raw: - log('[RAW] << {}'.format(data)) - - msg = json.loads(str(data)) - - changed_pending = False - - with self.pending_condition: - if msg.get('msg') == 'error': - log("* ERROR {}".format(msg['reason'])) - # Reset all pending state - self.pending = {} - changed_pending = True - - elif msg.get('msg') == 'connected': - log("* CONNECTED") - - elif msg.get('msg') == 'failed': - log("* FAILED; suggested version {}".format(msg['version'])) - - elif msg.get('msg') == 'result': - if msg['id'] == self.pending.get('id'): - if msg.get('result'): - log("* METHOD RESULT {}".format(msg['result'])) - elif msg.get('error'): - log("* ERROR {}".format(msg['error']['reason'])) - else: - log("* METHOD FINISHED") - self.pending.update({'result_acked': True}) - changed_pending = True - - elif msg.get('msg') == 'added': - log("* ADDED {} {}".format( - msg['collection'], msg['id'])) - if 'fields' in msg: - for key, value in msg['fields'].items(): - log(" - FIELD {} {}".format(key, value)) - elif msg.get('msg') == 'changed': - log("* CHANGED {} {}".format( - msg['collection'], msg['id'])) - if 'fields' in msg: - for key, value in msg['fields'].items(): - log(" - FIELD {} {}".format(key, value)) - if 'cleared' in msg: - for key in msg['cleared']: - log(" - CLEARED {}".format(key)); - elif msg.get('msg') == 'removed': - log("* REMOVED {} {}".format( - msg['collection'], ", ".join(msg['ids']))) - elif msg.get('msg') == 'ready': - assert 'subs' in msg - if self.pending.get('id') in msg['subs']: - log("* READY") - self.pending.update({'data_acked': True}) - changed_pending = True - elif msg.get('msg') == 'updated': - if self.pending.get('id') in msg['methods']: - log("* UPDATED") - self.pending.update({'data_acked': True}) - changed_pending = True - elif msg.get('msg') == 'nosub': - log("* NOSUB") - self.pending.update({'data_acked': True}) - changed_pending = True - - if changed_pending: - self.pending_condition.notify() - - def closed(self, code, reason=None): - """Called when the connection is closed""" - log('* CONNECTION CLOSED {} {}'.format(code, reason)) - - # Overrides WebSocket to run to ensure that if an unhandled exception is - # thrown in the thread, we print the exception and *then* kill the main - # thread. - def run(self): - try: - super(DDPClient, self).run() - except: - traceback.print_exc() - finally: - with self.pending_condition: - self.pending_condition.notify() - thread.interrupt_main() - - -class App(Cmd): - """Main input loop.""" - - def __init__(self, ddp_endpoint, print_raw): - Cmd.__init__(self) - - # Should we print the raw websocket messages in addition to - # parsing them? - self.print_raw = print_raw - - # This is the websocket client that will actually talk with - # meteor - self.ddpclient = DDPClient( - 'ws://' + ddp_endpoint + '/websocket', - self.print_raw) - self.ddpclient.connect() - - # Showing a fancy prompt string if we're interactive - if sys.stdin.isatty(): - self.prompt = ddp_endpoint + '> ' - else: - self.prompt = '' - - # Initializing the message id counter that will be incremented - # by the `next_id() method - self.unique_id = 0 - - def do_call(self, params): - """The `call` command""" - try: - method_name, params = parse_command(params) - except ValueError: - log('Error parsing parameter list - try `help call`') - return - self.ddpclient.send({ - "msg": "method", - "method": method_name, - "params": params, - "id": self.next_id(), - }) - - def do_sub(self, params): - """The `sub` command""" - try: - sub_name, params = parse_command(params) - except ValueError: - log('Error parsing parameter list - try `help sub`') - return - self.ddpclient.send({ - "msg": "sub", - "name": sub_name, - "params": params, - "id": self.next_id(), - }) - - def do_EOF(self, line): - """The `EOF` "command" - - It's here to support `cat file | python ddpclient.py` - """ - return True - - def do_help(self, line): - """The `help` command""" - - msgs = { - 'call': ( - 'call \n' - ' Calls a remote method\n' - ' Example: call vote ["foo.meteor.com"]'), - 'sub': ( - 'sub []\n' - ' Subscribes to a remote dataset\n' - ' Examples: `sub allApps` or `sub myApp ' - '["foo.meteor.com"]`'), - } - - line = line.strip() - if line and line in msgs: - return log('\n' + msgs[line]) - - for msg in msgs.values(): - log('\n' + msg) - - def emptyline(self): - """Disable the default Cmd empty line behavior""" - pass - - def next_id(self): - """Calculates the next id for messages that will be sent to the - server""" - self.unique_id = self.unique_id + 1 - return str(self.unique_id) - - -def main(): - """Parse the command line arguments and create a new App instance""" - parser = argparse.ArgumentParser( - description='A command-line tool for communicating with a DDP server.') - parser.add_argument( - 'ddp_endpoint', metavar='ddp_endpoint', - help='DDP websocket endpoint to connect ' + - 'to, e.g. madewith.meteor.com') - parser.add_argument( - '--print-raw', dest='print_raw', action="store_true", - help='print raw websocket data in addition to parsed results') - args = parser.parse_args() - - app = App(args.ddp_endpoint, args.print_raw) - try: - app.cmdloop() - except KeyboardInterrupt: - # On Ctrl-C or thread.interrupt_main(), just exit without printing a - # traceback. - pass - - -if __name__ == '__main__': - main() diff --git a/examples/unfinished/python-ddp-client/test_input b/examples/unfinished/python-ddp-client/test_input deleted file mode 100644 index 07da1e3b20..0000000000 --- a/examples/unfinished/python-ddp-client/test_input +++ /dev/null @@ -1,22 +0,0 @@ -sub -sub undefinedSub -sub undefinedSub someArg -sub undefinedSub {} -sub allApps -sub myApp "foo.bar" -sub myApp ["foo.meteor.com"] - -call -call undefinedMethod -call undefinedMethod yzyz -call undefinedMethod {} -call vote -call vote [] -call vote ["foo.meteor.com"] -call vote ["madewith.meteor.com"] -call vote {} - -help -help sub -help call - diff --git a/examples/unfinished/reorderable-list/.meteor/.gitignore b/examples/unfinished/reorderable-list/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/reorderable-list/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/reorderable-list/.meteor/packages b/examples/unfinished/reorderable-list/.meteor/packages deleted file mode 100644 index e442b00306..0000000000 --- a/examples/unfinished/reorderable-list/.meteor/packages +++ /dev/null @@ -1,8 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -standard-app-packages -autopublish -insecure diff --git a/examples/unfinished/reorderable-list/.meteor/release b/examples/unfinished/reorderable-list/.meteor/release deleted file mode 100644 index 621e94f0ec..0000000000 --- a/examples/unfinished/reorderable-list/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -none diff --git a/examples/unfinished/reorderable-list/client/jquery-ui-sortable.js b/examples/unfinished/reorderable-list/client/jquery-ui-sortable.js deleted file mode 100755 index 0d85cfa365..0000000000 --- a/examples/unfinished/reorderable-list/client/jquery-ui-sortable.js +++ /dev/null @@ -1,2252 +0,0 @@ -/*! jQuery UI - v1.10.3 - 2013-07-30 -* http://jqueryui.com -* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js -* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ - -(function( $, undefined ) { - -var uuid = 0, - runiqueId = /^ui-id-\d+$/; - -// $.ui might exist from components with no dependencies, e.g., $.ui.position -$.ui = $.ui || {}; - -$.extend( $.ui, { - version: "1.10.3", - - keyCode: { - BACKSPACE: 8, - COMMA: 188, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - LEFT: 37, - NUMPAD_ADD: 107, - NUMPAD_DECIMAL: 110, - NUMPAD_DIVIDE: 111, - NUMPAD_ENTER: 108, - NUMPAD_MULTIPLY: 106, - NUMPAD_SUBTRACT: 109, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SPACE: 32, - TAB: 9, - UP: 38 - } -}); - -// plugins -$.fn.extend({ - focus: (function( orig ) { - return function( delay, fn ) { - return typeof delay === "number" ? - this.each(function() { - var elem = this; - setTimeout(function() { - $( elem ).focus(); - if ( fn ) { - fn.call( elem ); - } - }, delay ); - }) : - orig.apply( this, arguments ); - }; - })( $.fn.focus ), - - scrollParent: function() { - var scrollParent; - if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { - scrollParent = this.parents().filter(function() { - return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); - }).eq(0); - } else { - scrollParent = this.parents().filter(function() { - return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); - }).eq(0); - } - - return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; - }, - - zIndex: function( zIndex ) { - if ( zIndex !== undefined ) { - return this.css( "zIndex", zIndex ); - } - - if ( this.length ) { - var elem = $( this[ 0 ] ), position, value; - while ( elem.length && elem[ 0 ] !== document ) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned - position = elem.css( "position" ); - if ( position === "absolute" || position === "relative" || position === "fixed" ) { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - //
- value = parseInt( elem.css( "zIndex" ), 10 ); - if ( !isNaN( value ) && value !== 0 ) { - return value; - } - } - elem = elem.parent(); - } - } - - return 0; - }, - - uniqueId: function() { - return this.each(function() { - if ( !this.id ) { - this.id = "ui-id-" + (++uuid); - } - }); - }, - - removeUniqueId: function() { - return this.each(function() { - if ( runiqueId.test( this.id ) ) { - $( this ).removeAttr( "id" ); - } - }); - } -}); - -// selectors -function focusable( element, isTabIndexNotNaN ) { - var map, mapName, img, - nodeName = element.nodeName.toLowerCase(); - if ( "area" === nodeName ) { - map = element.parentNode; - mapName = map.name; - if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { - return false; - } - img = $( "img[usemap=#" + mapName + "]" )[0]; - return !!img && visible( img ); - } - return ( /input|select|textarea|button|object/.test( nodeName ) ? - !element.disabled : - "a" === nodeName ? - element.href || isTabIndexNotNaN : - isTabIndexNotNaN) && - // the element and all of its ancestors must be visible - visible( element ); -} - -function visible( element ) { - return $.expr.filters.visible( element ) && - !$( element ).parents().addBack().filter(function() { - return $.css( this, "visibility" ) === "hidden"; - }).length; -} - -$.extend( $.expr[ ":" ], { - data: $.expr.createPseudo ? - $.expr.createPseudo(function( dataName ) { - return function( elem ) { - return !!$.data( elem, dataName ); - }; - }) : - // support: jQuery <1.8 - function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - }, - - focusable: function( element ) { - return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); - }, - - tabbable: function( element ) { - var tabIndex = $.attr( element, "tabindex" ), - isTabIndexNaN = isNaN( tabIndex ); - return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); - } -}); - -// support: jQuery <1.8 -if ( !$( "
" ).outerWidth( 1 ).jquery ) { - $.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; - - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; - if ( border ) { - size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; - } - if ( margin ) { - size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - - return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); - }); - }; - - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } - - return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); - }); - }; - }); -} - -// support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - -// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) -if ( $( "" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { - $.fn.removeData = (function( removeData ) { - return function( key ) { - if ( arguments.length ) { - return removeData.call( this, $.camelCase( key ) ); - } else { - return removeData.call( this ); - } - }; - })( $.fn.removeData ); -} - - - - - -// deprecated -$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); - -$.support.selectstart = "onselectstart" in document.createElement( "div" ); -$.fn.extend({ - disableSelection: function() { - return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + - ".ui-disableSelection", function( event ) { - event.preventDefault(); - }); - }, - - enableSelection: function() { - return this.unbind( ".ui-disableSelection" ); - } -}); - -$.extend( $.ui, { - // $.ui.plugin is deprecated. Use $.widget() extensions instead. - plugin: { - add: function( module, option, set ) { - var i, - proto = $.ui[ module ].prototype; - for ( i in set ) { - proto.plugins[ i ] = proto.plugins[ i ] || []; - proto.plugins[ i ].push( [ option, set[ i ] ] ); - } - }, - call: function( instance, name, args ) { - var i, - set = instance.plugins[ name ]; - if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { - return; - } - - for ( i = 0; i < set.length; i++ ) { - if ( instance.options[ set[ i ][ 0 ] ] ) { - set[ i ][ 1 ].apply( instance.element, args ); - } - } - } - }, - - // only used by resizable - hasScroll: function( el, a ) { - - //If overflow is hidden, the element might have extra content, but the user wants to hide it - if ( $( el ).css( "overflow" ) === "hidden") { - return false; - } - - var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", - has = false; - - if ( el[ scroll ] > 0 ) { - return true; - } - - // TODO: determine which cases actually cause this to happen - // if the element doesn't have the scroll set, see if it's possible to - // set the scroll - el[ scroll ] = 1; - has = ( el[ scroll ] > 0 ); - el[ scroll ] = 0; - return has; - } -}); - -})( jQuery ); -(function( $, undefined ) { - -var uuid = 0, - slice = Array.prototype.slice, - _cleanData = $.cleanData; -$.cleanData = function( elems ) { - for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { - try { - $( elem ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - _cleanData( elems ); -}; - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); -}; - -$.widget.extend = function( target ) { - var input = slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = slice.call( arguments, 1 ), - returnValue = this; - - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.widget.extend.apply( null, [ options ].concat(args) ) : - options; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} )._init(); - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - // 1.9 BC for #7810 - // TODO remove dual storage - .removeData( this.widgetName ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( value === undefined ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( value === undefined ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - - return this; - }, - - enable: function() { - return this._setOption( "disabled", false ); - }, - disable: function() { - return this._setOption( "disabled", true ); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - // accept selectors, DOM elements - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^(\w+)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -})( jQuery ); -(function( $, undefined ) { - -var mouseHandled = false; -$( document ).mouseup( function() { - mouseHandled = false; -}); - -$.widget("ui.mouse", { - version: "1.10.3", - options: { - cancel: "input,textarea,button,select,option", - distance: 1, - delay: 0 - }, - _mouseInit: function() { - var that = this; - - this.element - .bind("mousedown."+this.widgetName, function(event) { - return that._mouseDown(event); - }) - .bind("click."+this.widgetName, function(event) { - if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { - $.removeData(event.target, that.widgetName + ".preventClickEvent"); - event.stopImmediatePropagation(); - return false; - } - }); - - this.started = false; - }, - - // TODO: make sure destroying one instance of mouse doesn't mess with - // other instances of mouse - _mouseDestroy: function() { - this.element.unbind("."+this.widgetName); - if ( this._mouseMoveDelegate ) { - $(document) - .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); - } - }, - - _mouseDown: function(event) { - // don't let more than one widget handle mouseStart - if( mouseHandled ) { return; } - - // we may have missed mouseup (out of window) - (this._mouseStarted && this._mouseUp(event)); - - this._mouseDownEvent = event; - - var that = this, - btnIsLeft = (event.which === 1), - // event.target.nodeName works around a bug in IE 8 with - // disabled inputs (#7620) - elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { - return true; - } - - this.mouseDelayMet = !this.options.delay; - if (!this.mouseDelayMet) { - this._mouseDelayTimer = setTimeout(function() { - that.mouseDelayMet = true; - }, this.options.delay); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = (this._mouseStart(event) !== false); - if (!this._mouseStarted) { - event.preventDefault(); - return true; - } - } - - // Click event may never have fired (Gecko & Opera) - if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { - $.removeData(event.target, this.widgetName + ".preventClickEvent"); - } - - // these delegates are required to keep context - this._mouseMoveDelegate = function(event) { - return that._mouseMove(event); - }; - this._mouseUpDelegate = function(event) { - return that._mouseUp(event); - }; - $(document) - .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .bind("mouseup."+this.widgetName, this._mouseUpDelegate); - - event.preventDefault(); - - mouseHandled = true; - return true; - }, - - _mouseMove: function(event) { - // IE mouseup check - mouseup happened when mouse was out of window - if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { - return this._mouseUp(event); - } - - if (this._mouseStarted) { - this._mouseDrag(event); - return event.preventDefault(); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = - (this._mouseStart(this._mouseDownEvent, event) !== false); - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); - } - - return !this._mouseStarted; - }, - - _mouseUp: function(event) { - $(document) - .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); - - if (this._mouseStarted) { - this._mouseStarted = false; - - if (event.target === this._mouseDownEvent.target) { - $.data(event.target, this.widgetName + ".preventClickEvent", true); - } - - this._mouseStop(event); - } - - return false; - }, - - _mouseDistanceMet: function(event) { - return (Math.max( - Math.abs(this._mouseDownEvent.pageX - event.pageX), - Math.abs(this._mouseDownEvent.pageY - event.pageY) - ) >= this.options.distance - ); - }, - - _mouseDelayMet: function(/* event */) { - return this.mouseDelayMet; - }, - - // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(/* event */) {}, - _mouseDrag: function(/* event */) {}, - _mouseStop: function(/* event */) {}, - _mouseCapture: function(/* event */) { return true; } -}); - -})(jQuery); -(function( $, undefined ) { - -/*jshint loopfunc: true */ - -function isOverAxis( x, reference, size ) { - return ( x > reference ) && ( x < ( reference + size ) ); -} - -function isFloating(item) { - return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); -} - -$.widget("ui.sortable", $.ui.mouse, { - version: "1.10.3", - widgetEventPrefix: "sort", - ready: false, - options: { - appendTo: "parent", - axis: false, - connectWith: false, - containment: false, - cursor: "auto", - cursorAt: false, - dropOnEmpty: true, - forcePlaceholderSize: false, - forceHelperSize: false, - grid: false, - handle: false, - helper: "original", - items: "> *", - opacity: false, - placeholder: false, - revert: false, - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - scope: "default", - tolerance: "intersect", - zIndex: 1000, - - // callbacks - activate: null, - beforeStop: null, - change: null, - deactivate: null, - out: null, - over: null, - receive: null, - remove: null, - sort: null, - start: null, - stop: null, - update: null - }, - _create: function() { - - var o = this.options; - this.containerCache = {}; - this.element.addClass("ui-sortable"); - - //Get the items - this.refresh(); - - //Let's determine if the items are being displayed horizontally - this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; - - //Let's determine the parent's offset - this.offset = this.element.offset(); - - //Initialize mouse events for interaction - this._mouseInit(); - - //We're ready to go - this.ready = true; - - }, - - _destroy: function() { - this.element - .removeClass("ui-sortable ui-sortable-disabled"); - this._mouseDestroy(); - - for ( var i = this.items.length - 1; i >= 0; i-- ) { - this.items[i].item.removeData(this.widgetName + "-item"); - } - - return this; - }, - - _setOption: function(key, value){ - if ( key === "disabled" ) { - this.options[ key ] = value; - - this.widget().toggleClass( "ui-sortable-disabled", !!value ); - } else { - // Don't call widget base _setOption for disable as it adds ui-state-disabled class - $.Widget.prototype._setOption.apply(this, arguments); - } - }, - - _mouseCapture: function(event, overrideHandle) { - var currentItem = null, - validHandle = false, - that = this; - - if (this.reverting) { - return false; - } - - if(this.options.disabled || this.options.type === "static") { - return false; - } - - //We have to refresh the items data once first - this._refreshItems(event); - - //Find out if the clicked node (or one of its parents) is a actual item in this.items - $(event.target).parents().each(function() { - if($.data(this, that.widgetName + "-item") === that) { - currentItem = $(this); - return false; - } - }); - if($.data(event.target, that.widgetName + "-item") === that) { - currentItem = $(event.target); - } - - if(!currentItem) { - return false; - } - if(this.options.handle && !overrideHandle) { - $(this.options.handle, currentItem).find("*").addBack().each(function() { - if(this === event.target) { - validHandle = true; - } - }); - if(!validHandle) { - return false; - } - } - - this.currentItem = currentItem; - this._removeCurrentsFromItems(); - return true; - - }, - - _mouseStart: function(event, overrideHandle, noActivation) { - - var i, body, - o = this.options; - - this.currentContainer = this; - - //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture - this.refreshPositions(); - - //Create and append the visible helper - this.helper = this._createHelper(event); - - //Cache the helper size - this._cacheHelperProportions(); - - /* - * - Position generation - - * This block generates everything position related - it's the core of draggables. - */ - - //Cache the margins of the original element - this._cacheMargins(); - - //Get the next scrolling parent - this.scrollParent = this.helper.scrollParent(); - - //The element's absolute position on the page minus margins - this.offset = this.currentItem.offset(); - this.offset = { - top: this.offset.top - this.margins.top, - left: this.offset.left - this.margins.left - }; - - $.extend(this.offset, { - click: { //Where the click happened, relative to the element - left: event.pageX - this.offset.left, - top: event.pageY - this.offset.top - }, - parent: this._getParentOffset(), - relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper - }); - - // Only after we got the offset, we can change the helper's position to absolute - // TODO: Still need to figure out a way to make relative sorting possible - this.helper.css("position", "absolute"); - this.cssPosition = this.helper.css("position"); - - //Generate the original position - this.originalPosition = this._generatePosition(event); - this.originalPageX = event.pageX; - this.originalPageY = event.pageY; - - //Adjust the mouse offset relative to the helper if "cursorAt" is supplied - (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); - - //Cache the former DOM position - this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; - - //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way - if(this.helper[0] !== this.currentItem[0]) { - this.currentItem.hide(); - } - - //Create the placeholder - this._createPlaceholder(); - - //Set a containment if given in the options - if(o.containment) { - this._setContainment(); - } - - if( o.cursor && o.cursor !== "auto" ) { // cursor option - body = this.document.find( "body" ); - - // support: IE - this.storedCursor = body.css( "cursor" ); - body.css( "cursor", o.cursor ); - - this.storedStylesheet = $( "" ).appendTo( body ); - } - - if(o.opacity) { // opacity option - if (this.helper.css("opacity")) { - this._storedOpacity = this.helper.css("opacity"); - } - this.helper.css("opacity", o.opacity); - } - - if(o.zIndex) { // zIndex option - if (this.helper.css("zIndex")) { - this._storedZIndex = this.helper.css("zIndex"); - } - this.helper.css("zIndex", o.zIndex); - } - - //Prepare scrolling - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { - this.overflowOffset = this.scrollParent.offset(); - } - - //Call callbacks - this._trigger("start", event, this._uiHash()); - - //Recache the helper size - if(!this._preserveHelperProportions) { - this._cacheHelperProportions(); - } - - - //Post "activate" events to possible containers - if( !noActivation ) { - for ( i = this.containers.length - 1; i >= 0; i-- ) { - this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); - } - } - - //Prepare possible droppables - if($.ui.ddmanager) { - $.ui.ddmanager.current = this; - } - - if ($.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - - this.dragging = true; - - this.helper.addClass("ui-sortable-helper"); - this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position - return true; - - }, - - _mouseDrag: function(event) { - var i, item, itemElement, intersection, - o = this.options, - scrolled = false; - - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); - - if (!this.lastPositionAbs) { - this.lastPositionAbs = this.positionAbs; - } - - //Do scrolling - if(this.options.scroll) { - if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { - - if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; - } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { - this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; - } - - if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; - } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { - this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; - } - - } else { - - if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); - } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { - scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); - } - - if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); - } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { - scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); - } - - } - - if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - } - - //Regenerate the absolute position used for position checks - this.positionAbs = this._convertPositionTo("absolute"); - - //Set the helper position - if(!this.options.axis || this.options.axis !== "y") { - this.helper[0].style.left = this.position.left+"px"; - } - if(!this.options.axis || this.options.axis !== "x") { - this.helper[0].style.top = this.position.top+"px"; - } - - //Rearrange - for (i = this.items.length - 1; i >= 0; i--) { - - //Cache variables and intersection, continue if no intersection - item = this.items[i]; - itemElement = item.item[0]; - intersection = this._intersectsWithPointer(item); - if (!intersection) { - continue; - } - - // Only put the placeholder inside the current Container, skip all - // items form other containers. This works because when moving - // an item from one container to another the - // currentContainer is switched before the placeholder is moved. - // - // Without this moving items in "sub-sortables" can cause the placeholder to jitter - // beetween the outer and inner container. - if (item.instance !== this.currentContainer) { - continue; - } - - // cannot intersect with itself - // no useless actions that have been done before - // no action if the item moved is the parent of the item checked - if (itemElement !== this.currentItem[0] && - this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && - !$.contains(this.placeholder[0], itemElement) && - (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) - ) { - - this.direction = intersection === 1 ? "down" : "up"; - - if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { - this._rearrange(event, item); - } else { - break; - } - - this._trigger("change", event, this._uiHash()); - break; - } - } - - //Post events to containers - this._contactContainers(event); - - //Interconnect with droppables - if($.ui.ddmanager) { - $.ui.ddmanager.drag(this, event); - } - - //Call callbacks - this._trigger("sort", event, this._uiHash()); - - this.lastPositionAbs = this.positionAbs; - return false; - - }, - - _mouseStop: function(event, noPropagation) { - - if(!event) { - return; - } - - //If we are using droppables, inform the manager about the drop - if ($.ui.ddmanager && !this.options.dropBehaviour) { - $.ui.ddmanager.drop(this, event); - } - - if(this.options.revert) { - var that = this, - cur = this.placeholder.offset(), - axis = this.options.axis, - animation = {}; - - if ( !axis || axis === "x" ) { - animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); - } - if ( !axis || axis === "y" ) { - animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); - } - this.reverting = true; - $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { - that._clear(event); - }); - } else { - this._clear(event, noPropagation); - } - - return false; - - }, - - cancel: function() { - - if(this.dragging) { - - this._mouseUp({ target: null }); - - if(this.options.helper === "original") { - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - //Post deactivating events to containers - for (var i = this.containers.length - 1; i >= 0; i--){ - this.containers[i]._trigger("deactivate", null, this._uiHash(this)); - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", null, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - if (this.placeholder) { - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - if(this.placeholder[0].parentNode) { - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - } - if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { - this.helper.remove(); - } - - $.extend(this, { - helper: null, - dragging: false, - reverting: false, - _noFinalSort: null - }); - - if(this.domPosition.prev) { - $(this.domPosition.prev).after(this.currentItem); - } else { - $(this.domPosition.parent).prepend(this.currentItem); - } - } - - return this; - - }, - - serialize: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - str = []; - o = o || {}; - - $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); - if (res) { - str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); - } - }); - - if(!str.length && o.key) { - str.push(o.key + "="); - } - - return str.join("&"); - - }, - - toArray: function(o) { - - var items = this._getItemsAsjQuery(o && o.connected), - ret = []; - - o = o || {}; - - items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); - return ret; - - }, - - /* Be careful with the following core functions */ - _intersectsWith: function(item) { - - var x1 = this.positionAbs.left, - x2 = x1 + this.helperProportions.width, - y1 = this.positionAbs.top, - y2 = y1 + this.helperProportions.height, - l = item.left, - r = l + item.width, - t = item.top, - b = t + item.height, - dyClick = this.offset.click.top, - dxClick = this.offset.click.left, - isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), - isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), - isOverElement = isOverElementHeight && isOverElementWidth; - - if ( this.options.tolerance === "pointer" || - this.options.forcePointerForContainers || - (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) - ) { - return isOverElement; - } else { - - return (l < x1 + (this.helperProportions.width / 2) && // Right Half - x2 - (this.helperProportions.width / 2) < r && // Left Half - t < y1 + (this.helperProportions.height / 2) && // Bottom Half - y2 - (this.helperProportions.height / 2) < b ); // Top Half - - } - }, - - _intersectsWithPointer: function(item) { - - var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), - isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), - isOverElement = isOverElementHeight && isOverElementWidth, - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (!isOverElement) { - return false; - } - - return this.floating ? - ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) - : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); - - }, - - _intersectsWithSides: function(item) { - - var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), - isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (this.floating && horizontalDirection) { - return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); - } else { - return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); - } - - }, - - _getDragVerticalDirection: function() { - var delta = this.positionAbs.top - this.lastPositionAbs.top; - return delta !== 0 && (delta > 0 ? "down" : "up"); - }, - - _getDragHorizontalDirection: function() { - var delta = this.positionAbs.left - this.lastPositionAbs.left; - return delta !== 0 && (delta > 0 ? "right" : "left"); - }, - - refresh: function(event) { - this._refreshItems(event); - this.refreshPositions(); - return this; - }, - - _connectWith: function() { - var options = this.options; - return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; - }, - - _getItemsAsjQuery: function(connected) { - - var i, j, cur, inst, - items = [], - queries = [], - connectWith = this._connectWith(); - - if(connectWith && connected) { - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); - for ( j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); - } - } - } - } - - queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); - - for (i = queries.length - 1; i >= 0; i--){ - queries[i][0].each(function() { - items.push(this); - }); - } - - return $(items); - - }, - - _removeCurrentsFromItems: function() { - - var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); - - this.items = $.grep(this.items, function (item) { - for (var j=0; j < list.length; j++) { - if(list[j] === item.item[0]) { - return false; - } - } - return true; - }); - - }, - - _refreshItems: function(event) { - - this.items = []; - this.containers = [this]; - - var i, j, cur, inst, targetData, _queries, item, queriesLength, - items = this.items, - queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], - connectWith = this._connectWith(); - - if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down - for (i = connectWith.length - 1; i >= 0; i--){ - cur = $(connectWith[i]); - for (j = cur.length - 1; j >= 0; j--){ - inst = $.data(cur[j], this.widgetFullName); - if(inst && inst !== this && !inst.options.disabled) { - queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); - this.containers.push(inst); - } - } - } - } - - for (i = queries.length - 1; i >= 0; i--) { - targetData = queries[i][1]; - _queries = queries[i][0]; - - for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { - item = $(_queries[j]); - - item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) - - items.push({ - item: item, - instance: targetData, - width: 0, height: 0, - left: 0, top: 0 - }); - } - } - - }, - - refreshPositions: function(fast) { - - //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change - if(this.offsetParent && this.helper) { - this.offset.parent = this._getParentOffset(); - } - - var i, item, t, p; - - for (i = this.items.length - 1; i >= 0; i--){ - item = this.items[i]; - - //We ignore calculating positions of all connected containers when we're not over them - if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { - continue; - } - - t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; - - if (!fast) { - item.width = t.outerWidth(); - item.height = t.outerHeight(); - } - - p = t.offset(); - item.left = p.left; - item.top = p.top; - } - - if(this.options.custom && this.options.custom.refreshContainers) { - this.options.custom.refreshContainers.call(this); - } else { - for (i = this.containers.length - 1; i >= 0; i--){ - p = this.containers[i].element.offset(); - this.containers[i].containerCache.left = p.left; - this.containers[i].containerCache.top = p.top; - this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); - this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); - } - } - - return this; - }, - - _createPlaceholder: function(that) { - that = that || this; - var className, - o = that.options; - - if(!o.placeholder || o.placeholder.constructor === String) { - className = o.placeholder; - o.placeholder = { - element: function() { - - var nodeName = that.currentItem[0].nodeName.toLowerCase(), - element = $( "<" + nodeName + ">", that.document[0] ) - .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") - .removeClass("ui-sortable-helper"); - - if ( nodeName === "tr" ) { - that.currentItem.children().each(function() { - $( " ", that.document[0] ) - .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) - .appendTo( element ); - }); - } else if ( nodeName === "img" ) { - element.attr( "src", that.currentItem.attr( "src" ) ); - } - - if ( !className ) { - element.css( "visibility", "hidden" ); - } - - return element; - }, - update: function(container, p) { - - // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that - // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified - if(className && !o.forcePlaceholderSize) { - return; - } - - //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item - if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } - if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } - } - }; - } - - //Create the placeholder - that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); - - //Append it after the actual current item - that.currentItem.after(that.placeholder); - - //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) - o.placeholder.update(that, that.placeholder); - - }, - - _contactContainers: function(event) { - var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, - innermostContainer = null, - innermostIndex = null; - - // get innermost container that intersects with item - for (i = this.containers.length - 1; i >= 0; i--) { - - // never consider a container that's located within the item itself - if($.contains(this.currentItem[0], this.containers[i].element[0])) { - continue; - } - - if(this._intersectsWith(this.containers[i].containerCache)) { - - // if we've already found a container and it's more "inner" than this, then continue - if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { - continue; - } - - innermostContainer = this.containers[i]; - innermostIndex = i; - - } else { - // container doesn't intersect. trigger "out" event if necessary - if(this.containers[i].containerCache.over) { - this.containers[i]._trigger("out", event, this._uiHash(this)); - this.containers[i].containerCache.over = 0; - } - } - - } - - // if no intersecting containers found, return - if(!innermostContainer) { - return; - } - - // move the item into the container if it's not there already - if(this.containers.length === 1) { - if (!this.containers[innermostIndex].containerCache.over) { - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - } else { - - //When entering a new container, we will find the item with the least distance and append our item near it - dist = 10000; - itemWithLeastDistance = null; - floating = innermostContainer.floating || isFloating(this.currentItem); - posProperty = floating ? "left" : "top"; - sizeProperty = floating ? "width" : "height"; - base = this.positionAbs[posProperty] + this.offset.click[posProperty]; - for (j = this.items.length - 1; j >= 0; j--) { - if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { - continue; - } - if(this.items[j].item[0] === this.currentItem[0]) { - continue; - } - if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { - continue; - } - cur = this.items[j].item.offset()[posProperty]; - nearBottom = false; - if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ - nearBottom = true; - cur += this.items[j][sizeProperty]; - } - - if(Math.abs(cur - base) < dist) { - dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; - this.direction = nearBottom ? "up": "down"; - } - } - - //Check if dropOnEmpty is enabled - if(!itemWithLeastDistance && !this.options.dropOnEmpty) { - return; - } - - if(this.currentContainer === this.containers[innermostIndex]) { - return; - } - - itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); - this._trigger("change", event, this._uiHash()); - this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); - this.currentContainer = this.containers[innermostIndex]; - - //Update the placeholder - this.options.placeholder.update(this.currentContainer, this.placeholder); - - this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); - this.containers[innermostIndex].containerCache.over = 1; - } - - - }, - - _createHelper: function(event) { - - var o = this.options, - helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); - - //Add the helper to the DOM if that didn't happen already - if(!helper.parents("body").length) { - $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); - } - - if(helper[0] === this.currentItem[0]) { - this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; - } - - if(!helper[0].style.width || o.forceHelperSize) { - helper.width(this.currentItem.width()); - } - if(!helper[0].style.height || o.forceHelperSize) { - helper.height(this.currentItem.height()); - } - - return helper; - - }, - - _adjustOffsetFromHelper: function(obj) { - if (typeof obj === "string") { - obj = obj.split(" "); - } - if ($.isArray(obj)) { - obj = {left: +obj[0], top: +obj[1] || 0}; - } - if ("left" in obj) { - this.offset.click.left = obj.left + this.margins.left; - } - if ("right" in obj) { - this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; - } - if ("top" in obj) { - this.offset.click.top = obj.top + this.margins.top; - } - if ("bottom" in obj) { - this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; - } - }, - - _getParentOffset: function() { - - - //Get the offsetParent and cache its position - this.offsetParent = this.helper.offsetParent(); - var po = this.offsetParent.offset(); - - // This is a special case where we need to modify a offset calculated on start, since the following happened: - // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent - // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that - // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag - if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { - po.left += this.scrollParent.scrollLeft(); - po.top += this.scrollParent.scrollTop(); - } - - // This needs to be actually done for all browsers, since pageX/pageY includes this information - // with an ugly IE fix - if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { - po = { top: 0, left: 0 }; - } - - return { - top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), - left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) - }; - - }, - - _getRelativeOffset: function() { - - if(this.cssPosition === "relative") { - var p = this.currentItem.position(); - return { - top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), - left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() - }; - } else { - return { top: 0, left: 0 }; - } - - }, - - _cacheMargins: function() { - this.margins = { - left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), - top: (parseInt(this.currentItem.css("marginTop"),10) || 0) - }; - }, - - _cacheHelperProportions: function() { - this.helperProportions = { - width: this.helper.outerWidth(), - height: this.helper.outerHeight() - }; - }, - - _setContainment: function() { - - var ce, co, over, - o = this.options; - if(o.containment === "parent") { - o.containment = this.helper[0].parentNode; - } - if(o.containment === "document" || o.containment === "window") { - this.containment = [ - 0 - this.offset.relative.left - this.offset.parent.left, - 0 - this.offset.relative.top - this.offset.parent.top, - $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, - ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top - ]; - } - - if(!(/^(document|window|parent)$/).test(o.containment)) { - ce = $(o.containment)[0]; - co = $(o.containment).offset(); - over = ($(ce).css("overflow") !== "hidden"); - - this.containment = [ - co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, - co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, - co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, - co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - ]; - } - - }, - - _convertPositionTo: function(d, pos) { - - if(!pos) { - pos = this.position; - } - var mod = d === "absolute" ? 1 : -1, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, - scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - return { - top: ( - pos.top + // The absolute mouse position - this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) - ), - left: ( - pos.left + // The absolute mouse position - this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) - ) - }; - - }, - - _generatePosition: function(event) { - - var top, left, - o = this.options, - pageX = event.pageX, - pageY = event.pageY, - scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); - - // This is another very weird special case that only happens for relative elements: - // 1. If the css position is relative - // 2. and the scroll parent is the document or similar to the offset parent - // we have to refresh the relative offset during the scroll so there are no jumps - if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { - this.offset.relative = this._getRelativeOffset(); - } - - /* - * - Position constraining - - * Constrain the position to a mix of grid, containment. - */ - - if(this.originalPosition) { //If we are not dragging yet, we won't check for options - - if(this.containment) { - if(event.pageX - this.offset.click.left < this.containment[0]) { - pageX = this.containment[0] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top < this.containment[1]) { - pageY = this.containment[1] + this.offset.click.top; - } - if(event.pageX - this.offset.click.left > this.containment[2]) { - pageX = this.containment[2] + this.offset.click.left; - } - if(event.pageY - this.offset.click.top > this.containment[3]) { - pageY = this.containment[3] + this.offset.click.top; - } - } - - if(o.grid) { - top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; - pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; - - left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; - pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; - } - - } - - return { - top: ( - pageY - // The absolute mouse position - this.offset.click.top - // Click offset (relative to the element) - this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.top + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) - ), - left: ( - pageX - // The absolute mouse position - this.offset.click.left - // Click offset (relative to the element) - this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent - this.offset.parent.left + // The offsetParent's offset without borders (offset + border) - ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) - ) - }; - - }, - - _rearrange: function(event, i, a, hardRefresh) { - - a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); - - //Various things done here to improve the performance: - // 1. we create a setTimeout, that calls refreshPositions - // 2. on the instance, we have a counter variable, that get's higher after every append - // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same - // 4. this lets only the last addition to the timeout stack through - this.counter = this.counter ? ++this.counter : 1; - var counter = this.counter; - - this._delay(function() { - if(counter === this.counter) { - this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove - } - }); - - }, - - _clear: function(event, noPropagation) { - - this.reverting = false; - // We delay all events that have to be triggered to after the point where the placeholder has been removed and - // everything else normalized again - var i, - delayedTriggers = []; - - // We first have to update the dom position of the actual currentItem - // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) - if(!this._noFinalSort && this.currentItem.parent().length) { - this.placeholder.before(this.currentItem); - } - this._noFinalSort = null; - - if(this.helper[0] === this.currentItem[0]) { - for(i in this._storedCSS) { - if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { - this._storedCSS[i] = ""; - } - } - this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); - } else { - this.currentItem.show(); - } - - if(this.fromOutside && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); - } - if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { - delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed - } - - // Check if the items Container has Changed and trigger appropriate - // events. - if (this !== this.currentContainer) { - if(!noPropagation) { - delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); - delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); - } - } - - - //Post events to containers - for (i = this.containers.length - 1; i >= 0; i--){ - if(!noPropagation) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - } - if(this.containers[i].containerCache.over) { - delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); - this.containers[i].containerCache.over = 0; - } - } - - //Do what was originally in plugins - if ( this.storedCursor ) { - this.document.find( "body" ).css( "cursor", this.storedCursor ); - this.storedStylesheet.remove(); - } - if(this._storedOpacity) { - this.helper.css("opacity", this._storedOpacity); - } - if(this._storedZIndex) { - this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); - } - - this.dragging = false; - if(this.cancelHelperRemoval) { - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - for (i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return false; - } - - if(!noPropagation) { - this._trigger("beforeStop", event, this._uiHash()); - } - - //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! - this.placeholder[0].parentNode.removeChild(this.placeholder[0]); - - if(this.helper[0] !== this.currentItem[0]) { - this.helper.remove(); - } - this.helper = null; - - if(!noPropagation) { - for (i=0; i < delayedTriggers.length; i++) { - delayedTriggers[i].call(this, event); - } //Trigger all delayed events - this._trigger("stop", event, this._uiHash()); - } - - this.fromOutside = false; - return true; - - }, - - _trigger: function() { - if ($.Widget.prototype._trigger.apply(this, arguments) === false) { - this.cancel(); - } - }, - - _uiHash: function(_inst) { - var inst = _inst || this; - return { - helper: inst.helper, - placeholder: inst.placeholder || $([]), - position: inst.position, - originalPosition: inst.originalPosition, - offset: inst.positionAbs, - item: inst.currentItem, - sender: _inst ? _inst.element : null - }; - } - -}); - -})(jQuery); diff --git a/examples/unfinished/reorderable-list/client/shark.css b/examples/unfinished/reorderable-list/client/shark.css deleted file mode 100644 index c6a9f2e7f5..0000000000 --- a/examples/unfinished/reorderable-list/client/shark.css +++ /dev/null @@ -1,10 +0,0 @@ -#list div { - padding: 10px; - height: 19px; - border: 1px solid #bbb; - margin: 8px; - font-weight: bold; - cursor: move; - width: 400px; - background: #eee; } - diff --git a/examples/unfinished/reorderable-list/client/shark.html b/examples/unfinished/reorderable-list/client/shark.html deleted file mode 100644 index e65e597c2d..0000000000 --- a/examples/unfinished/reorderable-list/client/shark.html +++ /dev/null @@ -1,9 +0,0 @@ - -
- {{#each items}} -
- {{text}} -
- {{/each}} -
- diff --git a/examples/unfinished/reorderable-list/client/shark.js b/examples/unfinished/reorderable-list/client/shark.js deleted file mode 100644 index 2ae26b746c..0000000000 --- a/examples/unfinished/reorderable-list/client/shark.js +++ /dev/null @@ -1,30 +0,0 @@ -UI.body.items = Items.find({}, { sort: { rank: 1 } }); - -SimpleRationalRanks = { - beforeFirst: function (firstRank) { return firstRank - 1; }, - between: function (beforeRank, afterRank) { return (beforeRank + afterRank) / 2; }, - afterLast: function (lastRank) { return lastRank + 1; } -}; - -UI.body.rendered = function () { - $(this.find('#list')).sortable({ // uses the 'sortable' interaction from jquery ui - stop: function (event, ui) { // fired when an item is dropped - var el = ui.item.get(0), before = ui.item.prev().get(0), after = ui.item.next().get(0); - - var newRank; - if (!before) { // moving to the top of the list - newRank = SimpleRationalRanks.beforeFirst(UI.getElementData(after).rank); - - } else if (!after) { // moving to the bottom of the list - newRank = SimpleRationalRanks.afterLast(UI.getElementData(before).rank); - - } else { - newRank = SimpleRationalRanks.between( - UI.getElementData(before).rank, - UI.getElementData(after).rank); - } - - Items.update(UI.getElementData(el)._id, {$set: {rank: newRank}}); - } - }); -}; diff --git a/examples/unfinished/reorderable-list/lib/items.js b/examples/unfinished/reorderable-list/lib/items.js deleted file mode 100644 index 91c12feea6..0000000000 --- a/examples/unfinished/reorderable-list/lib/items.js +++ /dev/null @@ -1,9 +0,0 @@ -Items = new Mongo.Collection("items"); - -if (Meteor.isServer) { - if (Items.find().count() === 0) { - _.each( - ["violet", "unicorn", "flask", "jar", "leitmotif", "rearrange", "right", "ethereal"], - function (text, index) { Items.insert({text: text, rank: index}); }); - } -} diff --git a/examples/unfinished/todos-backbone/.meteor/.gitignore b/examples/unfinished/todos-backbone/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/todos-backbone/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/todos-backbone/.meteor/packages b/examples/unfinished/todos-backbone/.meteor/packages deleted file mode 100644 index c24acdbd36..0000000000 --- a/examples/unfinished/todos-backbone/.meteor/packages +++ /dev/null @@ -1,8 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -jquery -backbone -standard-app-packages diff --git a/examples/unfinished/todos-backbone/.meteor/release b/examples/unfinished/todos-backbone/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/todos-backbone/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/todos-backbone/body.html b/examples/unfinished/todos-backbone/body.html deleted file mode 100644 index fa8e5c01d2..0000000000 --- a/examples/unfinished/todos-backbone/body.html +++ /dev/null @@ -1,75 +0,0 @@ - -Todos - - - - - - -
- -
-

Todos

-
- -
- -
- - -
- -
-
    -
    - -
    - -
    - -
    - -
    - -
    - Created by -
    - Jérôme Gravel-Niquet -
    - - - - - - - - diff --git a/examples/unfinished/todos-backbone/client/todos.js b/examples/unfinished/todos-backbone/client/todos.js deleted file mode 100644 index cb9e610af6..0000000000 --- a/examples/unfinished/todos-backbone/client/todos.js +++ /dev/null @@ -1,201 +0,0 @@ -// An example Backbone application contributed by -// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple -// [LocalStorage adapter](backbone-localstorage.html) -// to persist Backbone models within your browser. - -// Load the application once the DOM is ready, using `jQuery.ready`: -$(function(){ - // ask for all the todos in my cache - Meteor.subscribe('todos'); - - // helper functions - - function all () { - return Todos.find(); - }; - - function all_done () { - return Todos.find({done: true}); - }; - - function all_remaining () { - return Todos.find({done: false}); - }; - - function nextOrder () { - var todos = Todos.find({}, {sort: {order: -1}, limit: 1}); - return todos[0] ? todos[0].order + 1 : 1; - }; - - // Todo Item View - // -------------- - - // The DOM element for a todo item... - window.TodoView = Backbone.View.extend({ - - //... is a list tag. - tagName: "li", - - // Cache the template function for a single item. - template: _.template($('#item-template').html()), - - // The DOM events specific to an item. - events: { - "click .check" : "toggleDone", - "dblclick div.todo-text" : "edit", - "click span.todo-destroy" : "clear", - "keypress .todo-input" : "updateOnEnter" - }, - - // Re-render the contents of the todo item. - render: function() { - $(this.el).html(this.template(this.model)); - this.setText(); - return this; - }, - - // To avoid XSS (not that it would be harmful in this particular app), - // we use `jQuery.text` to set the contents of the todo item. - setText: function() { - this.$('.todo-text').text(this.model.text); - this.input = this.$('.todo-input'); - this.input.bind('blur', _.bind(this.close, this)).val(this.model.text); - }, - - // Toggle the `"done"` state of the object. - toggleDone: function() { - Todos.update(this.model._id, {$set: {done: !this.model.done}}); - }, - - // Switch this view into `"editing"` mode, displaying the input field. - edit: function() { - $(this.el).addClass("editing"); - this.input.focus(); - }, - - // Close the `"editing"` mode, saving changes to the todo. - // findLive callback will update this view. - close: function() { - Todos.update(this.model._id, {$set: {text: this.input.val()}}); - $(this.el).removeClass("editing"); - }, - - // If you hit `enter`, we're through editing the item. - updateOnEnter: function(e) { - if (e.keyCode == 13) this.close(); - }, - - // Remove this view from the DOM. - remove: function() { - $(this.el).remove(); - }, - - // destroy the todo object. the findLive callback will g/c this view. - clear: function() { - Todos.remove(this.model._id); - } - }); - - // The Application - // --------------- - - // Our overall **AppView** is the top-level piece of UI. - window.AppView = Backbone.View.extend({ - - // Instead of generating a new element, bind to the existing skeleton of - // the App already present in the HTML. - el: $("#todoapp"), - - // Our template for the line of statistics at the bottom of the app. - statsTemplate: _.template($('#stats-template').html()), - - // Delegated events for creating new items, and clearing done ones. - events: { - "keypress #new-todo": "createOnEnter", - "keyup #new-todo": "showTooltip", - "click .todo-clear a": "clearCompleted" - }, - - todos: [], - - // At initialization we bind to the relevant events on the `Todos` - // collection, when items are added or changed. Kick things off by - // loading any preexisting todos that might be saved in *localStorage*. - initialize: function() { - var self = this; - - this.input = this.$("#new-todo"); - - // spin up the live query. ignore the return value since we never - // stop the query. - Todos.findLive({}, { - added: function (obj, before_idx) { - // add a view node to the DOM - var view = new TodoView({model: obj}); - self.todos.splice(before_idx, 0, view); - self.$("#todo-list").append(view.render().el); - self.render(); - }, - removed: function (obj, at_idx) { - // remove the view node from the DOM - var view = self.todos.splice(at_idx, 1); - view[0].remove(); - self.render(); - }, - changed: function (obj, at_idx) { - // update obj in existing view and rerender - self.todos[at_idx].model = obj; - self.todos[at_idx].render(); - self.render(); - }, - moved: function (old_idx, new_idx) { - // unimplemented -- items don't ever move - }, - sort: {'order': 1} - }); - }, - - // Re-rendering the App just means refreshing the statistics -- the rest - // of the app doesn't change. - render: function() { - console.log("RENDER", all().length, all_done().length, all_remaining().length); - - this.$('#todo-stats').html(this.statsTemplate({ - total: all().length, - done: all_done().length, - remaining: all_remaining().length - })); - }, - - // If you hit return in the main input field, and there is text to save, - // create new **Todo** model. - createOnEnter: function(e) { - var text = this.input.val(); - if (!text || e.keyCode != 13) return; - Todos.insert({text: text, done: false, order: nextOrder()}); - this.input.val(''); - }, - - // Clear all done todo items, destroying their models. - clearCompleted: function() { - _.each(all_done(), function (todo) { Todos.remove(todo._id); }); - return false; - }, - - // Lazily show the tooltip that tells you to press `enter` to save - // a new todo item, after one second. - showTooltip: function(e) { - var tooltip = this.$(".ui-tooltip-top"); - var val = this.input.val(); - tooltip.fadeOut(); - if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout); - if (val == '' || val == this.input.attr('placeholder')) return; - var show = function(){ tooltip.show().fadeIn(); }; - this.tooltipTimeout = _.delay(show, 1000); - } - }); - - // Finally, we kick things off by creating the **App**. - window.App = new AppView; - -}); diff --git a/examples/unfinished/todos-backbone/common.js b/examples/unfinished/todos-backbone/common.js deleted file mode 100644 index a12c5d85e5..0000000000 --- a/examples/unfinished/todos-backbone/common.js +++ /dev/null @@ -1,8 +0,0 @@ -Todos = new Mongo.Collection("todos"); -//Todos.schema({text: String, done: Boolean, order: Number}); - -if (Meteor.isServer) { - Meteor.publish('todos', function () { - return Todos.find(); - }); -} diff --git a/examples/unfinished/todos-backbone/public/destroy.png b/examples/unfinished/todos-backbone/public/destroy.png deleted file mode 100644 index f44a72e5f9..0000000000 Binary files a/examples/unfinished/todos-backbone/public/destroy.png and /dev/null differ diff --git a/examples/unfinished/todos-backbone/todos.css b/examples/unfinished/todos-backbone/todos.css deleted file mode 100644 index 61ab6cffd7..0000000000 --- a/examples/unfinished/todos-backbone/todos.css +++ /dev/null @@ -1,311 +0,0 @@ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} -body { - line-height: 1; - color: black; - background: white; -} -ol, ul { - list-style: none; -} -a img { - border: none; -} - -html { - background: #eeeeee; -} - body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.4em; - background: #eeeeee; - color: #333333; - } - -#todoapp { - width: 480px; - margin: 0 auto 40px; - background: white; - padding: 20px; - -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0; - -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0; - -o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0; - box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0; -} - #todoapp h1 { - font-size: 36px; - font-weight: bold; - text-align: center; - padding: 20px 0 30px 0; - line-height: 1; - } - -#create-todo { - position: relative; -} - #create-todo input { - width: 466px; - font-size: 24px; - font-family: inherit; - line-height: 1.4em; - border: 0; - outline: none; - padding: 6px; - border: 1px solid #999999; - -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - } - #create-todo input::-webkit-input-placeholder { - font-style: italic; - } - #create-todo span { - position: absolute; - z-index: 999; - width: 170px; - left: 50%; - margin-left: -85px; - } - -#todo-list { - margin-top: 10px; -} - #todo-list li { - padding: 12px 20px 11px 0; - position: relative; - font-size: 24px; - line-height: 1.1em; - border-bottom: 1px solid #cccccc; - } - #todo-list li:after { - content: "\0020"; - display: block; - height: 0; - clear: both; - overflow: hidden; - visibility: hidden; - } - #todo-list li.editing { - padding: 0; - border-bottom: 0; - } - #todo-list .editing .display, - #todo-list .edit { - display: none; - } - #todo-list .editing .edit { - display: block; - } - #todo-list .editing input { - width: 444px; - font-size: 24px; - font-family: inherit; - margin: 0; - line-height: 1.6em; - border: 0; - outline: none; - padding: 10px 7px 0px 27px; - border: 1px solid #999999; - -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; - } - #todo-list .check { - position: relative; - top: 9px; - margin: 0 10px 0 7px; - float: left; - } - #todo-list .done .todo-text { - text-decoration: line-through; - color: #777777; - } - #todo-list .todo-destroy { - position: absolute; - right: 5px; - top: 14px; - display: none; - cursor: pointer; - width: 20px; - height: 20px; - background: url(destroy.png) no-repeat 0 0; - } - #todo-list li:hover .todo-destroy { - display: block; - } - #todo-list .todo-destroy:hover { - background-position: 0 -20px; - } - -#todo-stats { - *zoom: 1; - margin-top: 10px; - color: #777777; -} - #todo-stats:after { - content: "\0020"; - display: block; - height: 0; - clear: both; - overflow: hidden; - visibility: hidden; - } - #todo-stats .todo-count { - float: left; - } - #todo-stats .todo-count .number { - font-weight: bold; - color: #333333; - } - #todo-stats .todo-clear { - float: right; - } - #todo-stats .todo-clear a { - color: #777777; - font-size: 12px; - } - #todo-stats .todo-clear a:visited { - color: #777777; - } - #todo-stats .todo-clear a:hover { - color: #336699; - } - -#instructions { - width: 520px; - margin: 10px auto; - color: #777777; - text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; - text-align: center; -} - #instructions a { - color: #336699; - } - -#credits { - width: 520px; - margin: 30px auto; - color: #999; - text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; - text-align: center; -} - #credits a { - color: #888; - } - - -/* - * François 'cahnory' Germain - */ -.ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left { - color:#ffffff; - cursor:normal; - display:-moz-inline-stack; - display:inline-block; - font-size:12px; - font-family:arial; - padding:.5em 1em; - position:relative; - text-align:center; - text-shadow:0 -1px 1px #111111; - -webkit-border-top-left-radius:4px ; - -webkit-border-top-right-radius:4px ; - -webkit-border-bottom-right-radius:4px ; - -webkit-border-bottom-left-radius:4px ; - -khtml-border-top-left-radius:4px ; - -khtml-border-top-right-radius:4px ; - -khtml-border-bottom-right-radius:4px ; - -khtml-border-bottom-left-radius:4px ; - -moz-border-radius-topleft:4px ; - -moz-border-radius-topright:4px ; - -moz-border-radius-bottomright:4px ; - -moz-border-radius-bottomleft:4px ; - border-top-left-radius:4px ; - border-top-right-radius:4px ; - border-bottom-right-radius:4px ; - border-bottom-left-radius:4px ; - -o-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444; - -moz-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444; - -khtml-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444; - -webkit-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444; - box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444; - background-color:#3b3b3b; - background-image:-moz-linear-gradient(top,#555555,#222222); - background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#555555),color-stop(1,#222222)); - filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222); - -ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222); -} -.ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after { - content:"\25B8"; - display:block; - font-size:2em; - height:0; - line-height:0; - position:absolute; -} -.ui-tooltip:after, .ui-tooltip-bottom:after { - color:#2a2a2a; - bottom:0; - left:1px; - text-align:center; - text-shadow:1px 0 2px #000000; - -o-transform:rotate(90deg); - -moz-transform:rotate(90deg); - -khtml-transform:rotate(90deg); - -webkit-transform:rotate(90deg); - width:100%; -} -.ui-tooltip-top:after { - bottom:auto; - color:#4f4f4f; - left:-2px; - top:0; - text-align:center; - text-shadow:none; - -o-transform:rotate(-90deg); - -moz-transform:rotate(-90deg); - -khtml-transform:rotate(-90deg); - -webkit-transform:rotate(-90deg); - width:100%; -} -.ui-tooltip-right:after { - color:#222222; - right:-0.375em; - top:50%; - margin-top:-.05em; - text-shadow:0 1px 2px #000000; - -o-transform:rotate(0); - -moz-transform:rotate(0); - -khtml-transform:rotate(0); - -webkit-transform:rotate(0); -} -.ui-tooltip-left:after { - color:#222222; - left:-0.375em; - top:50%; - margin-top:.1em; - text-shadow:0 -1px 2px #000000; - -o-transform:rotate(180deg); - -moz-transform:rotate(180deg); - -khtml-transform:rotate(180deg); - -webkit-transform:rotate(180deg); -} diff --git a/examples/unfinished/todos-underscore/.meteor/.gitignore b/examples/unfinished/todos-underscore/.meteor/.gitignore deleted file mode 100644 index 4083037423..0000000000 --- a/examples/unfinished/todos-underscore/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/examples/unfinished/todos-underscore/.meteor/packages b/examples/unfinished/todos-underscore/.meteor/packages deleted file mode 100644 index 6bbedad3c8..0000000000 --- a/examples/unfinished/todos-underscore/.meteor/packages +++ /dev/null @@ -1,9 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -jquery -jquery-layout -jquery-history -standard-app-packages diff --git a/examples/unfinished/todos-underscore/.meteor/release b/examples/unfinished/todos-underscore/.meteor/release deleted file mode 100644 index a918a2aa18..0000000000 --- a/examples/unfinished/todos-underscore/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -0.6.0 diff --git a/examples/unfinished/todos-underscore/body.html b/examples/unfinished/todos-underscore/body.html deleted file mode 100644 index 0739651c2d..0000000000 --- a/examples/unfinished/todos-underscore/body.html +++ /dev/null @@ -1,98 +0,0 @@ - -Todos - - - - -
    -
    -
    -
    - -
    -
    - -
      -
      -
      - -
      -
      - -
      - -
      -
      - -
      -
      -

      - To get started, create a new todo list in the left sidebar by - typing its name in the text box. Select a list by clicking on its - name, and rename by double clicking. The active list appears in - the main window pane. You can do the usual here: add items, check - them off as completed, and destroy items. You can also tag items - with one or more tags, by clicking the blue Add new tag - button to the right. All your in-use tags appear at the top. You - can filter the list items by selecting a tag, or click the - leftmost button to return to the full list. -

      - -

      - Inspired by Backbone's - Todo Demo, - with credit to - Jérôme Gravel-Niquet. -

      -
      -
      - - - - - - - - - - diff --git a/examples/unfinished/todos-underscore/client/client.js b/examples/unfinished/todos-underscore/client/client.js deleted file mode 100644 index 1ccb0c4f06..0000000000 --- a/examples/unfinished/todos-underscore/client/client.js +++ /dev/null @@ -1,258 +0,0 @@ -// quick jquery extension to bind text inputs to blur and RET. -$.fn.onBlurOrEnter = function (callback) { - this.bind('blur', callback); - this.bind('keypress', function (evt) { - if (evt.keyCode === 13 && $(this).val()) - callback.call(this, evt); - }); -}; - -// everything else happens after DOM is ready -$(function () { - $('body').layout({north__minSize: 50, - spacing_open: 10, - north__fxSettings: { direction: "vertical" }}); - - // cache the template function for a single item. - var item_template = _.template($('#item-template').html()); - - // this render function could be replaced with a handlebars - // template. underscore template isn't safe for user-entered data - // like the item text (XSS). - function renderItem (obj) { - // generate template for todo - var elt = $(item_template(obj)); - - // set text through jquery for XSS protection - elt.find('.todo-text').text(obj.text); - - // clicking the checkbox toggles done state - elt.find('.check').click(function () { - Todos.update(obj._id, {$set: {done: !obj.done}}); - }); - - // clicking destroy button removes the item - elt.find('.destroy').click(function () { - Todos.remove(obj._id); - }); - - // wire up tag destruction links - elt.find('.tag .remove').click(function () { - var tag = $(this).attr('name'); - $(this).parent().fadeOut(500, function () { - Todos.update(obj._id, {$pull: {tags: tag}}); - }); - }); - - // wire up add tag - elt.find('.addtag').click(function () { - $(this).hide(); - elt.find('.edittag').show(); - elt.find('.edittag input').focus(); - }); - - // wire up edit tag - elt.find('.edittag input').onBlurOrEnter(function () { - elt.find('.edittag').hide(); - elt.find('.addtag').show(); - if ($(this).val() !== '') - Todos.update(obj._id, {$addToSet: {tags: $(this).val()}}); - }); - - // doubleclick on todo text brings up the editor - elt.find('.todo-text').dblclick(function () { - elt.addClass('editing'); - - var input = elt.find('.todo-input'); - input.val(obj.text); - input.focus(); - input.select(); - - input.onBlurOrEnter(function () { - elt.removeClass('editing'); - if ($(this).val() !== '') - Todos.update(obj._id, {$set: {text: elt.find('.todo-input').val()}}); - }); - }); - - return elt[0]; - }; - - // construct new todo from text box - $('#new-todo').bind('keypress', function (evt) { - var list_id = Session.get('list_id'); - var tag = Session.get('tag_filter'); - - // prevent creation of a new todo if nothing is selected - if (!list_id) return; - - var text = $('#new-todo').val(); - - if (evt.keyCode === 13 && text) { - var obj = {text: text, - list_id: list_id, - done: false, - timestamp: (new Date()).getTime()}; - if (tag) obj.tags = [tag]; - - Todos.insert(obj); - $('#new-todo').val(''); - } - }); - - var current_list_stop; - function setCurrentList (list_id) { - Session.set('list_id', list_id); - - $('#items-view').show(); - - // kill current findLive render - if (current_list_stop) - current_list_stop.stop(); - - var query = {list_id: list_id}; - if (Session.get('tag_filter')) - query.tags = Session.get('tag_filter') - - // render individual todo list, stash kill function - current_list_stop = - Meteor.ui.renderList(Todos, $('#item-list'), { - selector: query, - sort: {timestamp: 1}, - render: renderItem, - events: {} - }); - }; - - // render list of lists in the left sidebar. - Meteor.ui.renderList(Lists, $('#lists'), { - sort: {name: 1}, - template: $('#list-template'), - events: { - 'click': function (evt) { - window.History.pushState({list_id: this._id}, - "Todos: " + this.name, - "/" + this._id); - }, - 'dblclick': function (evt) { - var list_elt = $(evt.currentTarget); - var input = list_elt.find('.list-name-input'); - - list_elt.addClass('editing'); - - input.val(this.name); - input.focus(); - input.select(); - - var _id = this._id; - input.onBlurOrEnter(function () { - list_elt.removeClass('editing'); - if (input.val() !== '') - Lists.update(_id, {$set: {name: input.val()}}); - }); - } - } - }); - - // construct new todo list from text box - $('#new-list').bind('keypress', function (evt) { - var text = $('#new-list').val(); - - if (evt.keyCode === 13 && text) { - var list = Lists.insert({name: text}); - $('#new-list').val(''); - window.History.pushState({list_id: list._id}, - "Todos: " + list.name, - "/" + list._id); - } - }); - - // tags and filters - - // the tag filter bar is easy to generate using a simple - // renderList() against a minimongo query. since minimongo doesn't - // support aggregate queries, construct a local collection to serve - // the same purpose, and drive the renderList() off of it. - - var LocalTags = new Mongo.Collection; - (function () { - function updateLocalTags() { - var real = _(Todos.find()).chain().pluck('tags').compact().flatten().uniq().value(); - real.unshift(null); // XXX fake tag - - var computed = _(LocalTags.find()).pluck('tag'); - - _.each(_.difference(real, computed), function (new_tag) { - LocalTags.insert({tag: new_tag}); - }); - - _.each(_.difference(computed, real), function (dead_tag) { - LocalTags.remove({tag: dead_tag}); - }); - }; - - Todos.findLive({}, { - added: function (obj, before_idx) { _.defer(updateLocalTags); }, - removed: function (id, at_idx) { _.defer(updateLocalTags); }, - changed: function (obj, at_idx) { _.defer(updateLocalTags); }, - }); - })(); - - // findLive() against the computed tag table. since we also want a - // show-all button, arrange for the computed table to always include - // a null placeholder tag, and for the template to render that as - // "Show all". always begin the user session with a null filter. - - Session.set('tag_filter', null); - - Meteor.ui.renderList(LocalTags, $('#tag-filter'), { - sort: {tag: 1}, - template: $('#tag-filter-template'), - events: { - 'click': function (evt) { - if (Session.equals('tag_filter', this.tag)) - Session.set('tag_filter', null); - else - Session.set('tag_filter', this.tag); - - setCurrentList(Session.get('list_id')); - } - } - }); - - // load list on statechange (which we drive from several places). - window.History.Adapter.bind(window, 'statechange', function () { - var state = window.History.getState(); - var list = Lists.find(state.data.list_id); - setCurrentList(list._id); - }); - - // subscribe to all available todo lists. once the inital load - // completes, navigate to the list specified by URL, if any. - Meteor.subscribe('lists', function () { - var initial_list_id = window.location.pathname.split('/')[1]; - var list; - - if (initial_list_id) { - list = Lists.find(initial_list_id); - } else { - var lists = Lists.find({}, {sort: {name: 1}, limit: 1}); - list = lists[0]; - } - - if (list) { - window.History.replaceState({list_id: list._id}, - "Todos: " + list.name, - "/" + list._id); - // replaceState doesn't always trigger statechange on reload. if - // you last reloaded the same page and the state is the same, it - // won't fire. so call this here. double calling is not great, but - // OK. - setCurrentList(list._id); - } - }); - - // subscribe to all the items in each list. no need for a callback - // here: todo items are never queried using collection.find(). - Meteor.subscribe('todos'); -}); diff --git a/examples/unfinished/todos-underscore/common.js b/examples/unfinished/todos-underscore/common.js deleted file mode 100644 index 3c18676a60..0000000000 --- a/examples/unfinished/todos-underscore/common.js +++ /dev/null @@ -1,22 +0,0 @@ -Lists = new Mongo.Collection("lists"); - -Todos = new Mongo.Collection("todos"); - -/* Schema support coming soon! - -Lists.schema({text: String}); - -Todos.schema({text: String, - done: Boolean, - tags: [String]}); -*/ - -if (Meteor.isServer) { - Meteor.publish('lists', function () { - return Lists.find(); - }); - - Meteor.publish('todos', function () { - return Todos.find(); - }); -} diff --git a/examples/unfinished/todos-underscore/main.css b/examples/unfinished/todos-underscore/main.css deleted file mode 100644 index 60e850487d..0000000000 --- a/examples/unfinished/todos-underscore/main.css +++ /dev/null @@ -1,221 +0,0 @@ -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.4em; - background: #eeeeee; - color: #333333; -} - -.ui-layout-north { - background: #dddddd; -} - -#tag-filter { - margin: 8px; -} - -#items-view { - display: none; - margin: 10px; -} - -#new-todo { - width: 466px; - font-size: 24px; - font-family: inherit; - line-height: 1.4em; - border: 0; - outline: none; - padding: 6px; - border: 1px solid #999999; - margin-left: 75px; -} - -.ui-layout-west { - padding: 10px; - border-right: solid 1px #cccccc; -} - -.ui-layout-south { - border-top: solid 1px black; - padding: 10px; - background: #cccccc; -} - -#help p { - margin: 8px; -} - -.ui-layout-center { - overflow: auto; -} - -#lists .list { - margin: 2px; - font-weight: bold; -} - -#lists .list-name .empty { - font-size: 0.9em; - font-style: italic; -} - -#lists .editing .display, -#lists .edit { - display: none; -} -#lists .editing .edit { - display: block; -} -#lists .editing input { - font-family: inherit; - margin: 0; - line-height: 1.6em; - border: 0; - outline: none; - padding: 10px 7px 0px 27px; - border: 1px solid #999999; -} -#lists .selected { - background-color: lightblue; -} - -/* todo items */ - -#item-list { - margin-top: 10px; -} - -#item-list li { - margin: 12px; - font-size: 24px; - line-height: 1.1em; - border-bottom: 1px solid #cccccc; - height: 50px; -} - -#item-list li:after { - content: "\0020"; - display: block; - height: 0; - clear: both; - overflow: hidden; - visibility: hidden; -} - -#item-list .destroy { - float: left; - width: 20px; - height: 20px; - cursor: pointer; - margin-top: 12px; - margin-left: 5px; -} - -#item-list li:hover .destroy { - background: url('/destroy.png') no-repeat 0 0; -} - -#item-list li .destroy:hover { - background-position: 0 -20px; -} - -#item-list .display { - float: left; - margin: 9px; -} - -#item-list .check { - float: left; - margin: 9px; -} - -#item-list .edit { - float: left; -} - -#item-list .todo-text { - float: left; -} - -#item-list li.editing { - padding: 0; -} - -#item-list .editing .display, -#item-list .edit { - display: none; -} - -#item-list .editing .edit { - display: block; -} - -#item-list .editing input { - width: 444px; - font-size: 24px; - font-family: inherit; - margin-left: 38px; - line-height: 1.6em; - border: 0; - outline: none; - border: 1px solid #999999; -} - -#item-list .done .todo-text { - text-decoration: line-through; - color: #777777; -} - -#item-list .item-tags { - float: right; -} - -/* tags */ - -.tag { - float: left; - - color: black; - background: #aaaaaa; - font-size: 16px; - font-weight: bold; - - cursor: pointer; - - border: 1px solid black; - border-radius: 2px; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - - padding: 1px 3px 1px 3px; - margin: 4px; -} - -.tag.addtag { - background: lightblue; - border: 1px dashed black; -} - -.tag.edittag { - display: none; -} - -.tag.selected { - background: lightblue; -} - -.tag .name { - float: left; -} - -.tag .remove { - margin-top: 5px; - margin-left: 5px; - float: left; - width: 16px; - height: 16px; - background-image: url("/close_16.png"); -} - - diff --git a/examples/unfinished/todos-underscore/public/close_16.png b/examples/unfinished/todos-underscore/public/close_16.png deleted file mode 100644 index c605b1ce94..0000000000 Binary files a/examples/unfinished/todos-underscore/public/close_16.png and /dev/null differ diff --git a/examples/unfinished/todos-underscore/public/destroy.png b/examples/unfinished/todos-underscore/public/destroy.png deleted file mode 100644 index f44a72e5f9..0000000000 Binary files a/examples/unfinished/todos-underscore/public/destroy.png and /dev/null differ diff --git a/examples/unfinished/todos-underscore/reset.css b/examples/unfinished/todos-underscore/reset.css deleted file mode 100644 index eaa88eed13..0000000000 --- a/examples/unfinished/todos-underscore/reset.css +++ /dev/null @@ -1,30 +0,0 @@ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, font, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; -} -body { - line-height: 1; - color: black; - background: white; -} -ol, ul { - list-style: none; -} -a img { - border: none; -} - diff --git a/examples/unfinished/todos-underscore/server/bootstrap.js b/examples/unfinished/todos-underscore/server/bootstrap.js deleted file mode 100644 index e991e59b1b..0000000000 --- a/examples/unfinished/todos-underscore/server/bootstrap.js +++ /dev/null @@ -1,21 +0,0 @@ -// if the database is empty on server start, create some sample data. -Meteor.startup(function () { - if (Lists.find().length === 0) { - var list1 = Lists.insert({name: 'Things to do'}); - Todos.insert({list_id: list1._id, - text: 'Write Meteor app', tags: ['fun']}); - Todos.insert({list_id: list1._id, - text: 'Drink beer', tags: ['fun', 'yum']}); - - var list2 = Lists.insert({name: 'Places to see'}); - Todos.insert({list_id: list2._id, text: 'San Francisco', - tags: ['yum']}); - Todos.insert({list_id: list2._id, text: 'Paris', - tags: ['fun']}); - Todos.insert({list_id: list2._id, text: 'Tokyo'}); - - var list3 = Lists.insert({name: 'People to meet'}); - Todos.insert({list_id: list3._id, - text: 'All the cool kids'}); - } -}); diff --git a/meteor b/meteor index 8496e54b47..0a1b5ad62e 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/usr/bin/env bash -BUNDLE_VERSION=12.18.3.2 +BUNDLE_VERSION=12.21.0.0 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/examples/unfinished/accounts-ui-viewer/.gitignore b/npm-packages/meteor-installer/.gitignore similarity index 100% rename from examples/unfinished/accounts-ui-viewer/.gitignore rename to npm-packages/meteor-installer/.gitignore diff --git a/npm-packages/meteor-installer/README.md b/npm-packages/meteor-installer/README.md new file mode 100644 index 0000000000..d2342843da --- /dev/null +++ b/npm-packages/meteor-installer/README.md @@ -0,0 +1,24 @@ +## Windows Meteor Installer + +Requires [Node.js](https://nodejs.org/) 8 or newer. + +Install Meteor on Windows by running: + +```bash +npm install --global meteor +``` + +If Meteor is already installed, it will do nothing. + +Uninstall by running: + +```bash +meteor-installer uninstall +npm uninstall -g meteor +``` + +The installer runs faster when [Windows Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) is enabled. The installation extracts a large number of small files, which Windows Defender can cause to be very slow. + +It is not recommended to run the installer and `meteor` as administrator. Otherwise, if the administrator is a separate user the `meteor` command might not always be found. + +If you use a node version manager that uses a separate global `node_modules` folder for each Node version, you will need to re-install the `meteor` npm package when changing to a Node version for the first time. Otherwise, the `meteor` command will no longer be found. diff --git a/npm-packages/meteor-installer/cli.js b/npm-packages/meteor-installer/cli.js new file mode 100644 index 0000000000..d53d38bc10 --- /dev/null +++ b/npm-packages/meteor-installer/cli.js @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const command = process.argv[2]; + +if (!command) { + console.log(` + Usage: meteor-installer + + Commands: + install + uninstall + `); + process.exit(1); +} + +if (command === 'install') { + require('./install.js'); +} else if (command === 'uninstall') { + const { uninstall } = require('./uninstall'); + uninstall(); +} else { + console.error(`Unrecognized command: ${command}`); + process.exit(1); +} diff --git a/npm-packages/meteor-installer/config.js b/npm-packages/meteor-installer/config.js new file mode 100644 index 0000000000..6d79647497 --- /dev/null +++ b/npm-packages/meteor-installer/config.js @@ -0,0 +1,19 @@ +const path = require('path'); + +const METEOR_LATEST_VERSION = '2.1'; + +const localAppData = process.env.LOCALAPPDATA; + +if (!localAppData) { + throw new Error('LOCALAPPDATA env var is not set.'); +} + +const meteorLocalFolder = '.meteor'; +const meteorPath = path.resolve(localAppData, meteorLocalFolder); + +module.exports = { + extractPath: localAppData, + meteorPath, + release: process.env.INSTALL_METEOR_VERSION || METEOR_LATEST_VERSION, + startedPath: path.resolve(localAppData, '.meteor-install-started.txt'), +} diff --git a/npm-packages/meteor-installer/extract.js b/npm-packages/meteor-installer/extract.js new file mode 100644 index 0000000000..560e02d292 --- /dev/null +++ b/npm-packages/meteor-installer/extract.js @@ -0,0 +1,110 @@ +const tar = require('tar'); +const sevenBin = require('7zip-bin'); +const Seven = require('node-7z'); +const fs = require('fs'); +const { resolve, dirname } = require('path'); + +function extractWith7Zip (tarPath, destination, onProgress) { + return new Promise((resolve, reject) => { + const stream = Seven.extractFull(tarPath, destination, { + $progress: true, + $bin: sevenBin.path7za, + }); + stream.on('progress', function (progress) { + onProgress(progress); + }); + + stream.on('error', function (err) { + return reject(err); + }); + + stream.on('end', function () { + return resolve(); + }); + }) +} + +function createSymlinks(symlinks, baseDir) { + symlinks.forEach(({ path, linkPath }) => { + try { + let resolveBase = resolve(baseDir, dirname(path)) + const result = fs.statSync(resolve(resolveBase, linkPath)); + + if (result.isDirectory()) { + fs.symlinkSync(linkPath, path, 'junction'); + } else { + fs.copyFileSync( + resolve(resolveBase, linkPath), + resolve(baseDir, path), + ) + } + } catch (e) { + console.log(path, linkPath); + console.error(e); + throw new Error('Unable to create symlink'); + } + }) +} + +function extractWithTar (tarPath, destination, onProgress) { + let symlinks = []; + + let total = 0; + // This takes a few seconds, but lets us show the progress + tar.t({ + sync: true, + file: tarPath, + onentry() { + total += 1; + } + }); + + let started = 0; + let timeout = null; + + return new Promise((resolve, reject) => { + tar.x({ + file: tarPath, + cwd: destination, + filter(path, entry) { + if (entry.type === 'SymbolicLink') { + symlinks.push({ + path: entry.path, + linkPath: entry.linkpath, + }); + return false; + } + + return true; + }, + onentry() { + started += 1; + + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + onProgress({ + percent: (started / total) * 100, + fileCount: started, + }); + }, 300); + } + } + }, (err) => { + if (timeout) { + clearTimeout(timeout); + } + + if (err) { + return reject(err); + } + createSymlinks(symlinks, destination); + resolve(); + }); + }); +} + +module.exports = { + extractWithTar, + extractWith7Zip, +} diff --git a/npm-packages/meteor-installer/install.js b/npm-packages/meteor-installer/install.js new file mode 100644 index 0000000000..5a5875512b --- /dev/null +++ b/npm-packages/meteor-installer/install.js @@ -0,0 +1,186 @@ +const { DownloaderHelper } = require('node-downloader-helper'); +const cliProgress = require('cli-progress'); +const Seven = require('node-7z'); +const path = require('path'); +const sevenBin = require('7zip-bin'); +const fs = require('fs'); +const tmp = require('tmp'); +const os = require('os'); +const { meteorPath, release, startedPath, extractPath } = require('./config.js'); +const { uninstall } = require('./uninstall'); +const { extractWithTar, extractWith7Zip } = require('./extract.js'); + +process.on('unhandledRejection', (err) => { + throw err; +}); + +if (os.platform() !== 'win32') { + console.error('Can only install on Windows'); + process.exit(1); +} + +if (os.arch() !== 'x64') { + console.error('The current architecture is not supported:', os.arch()); + process.exit(1); +} + +const tempPath = tmp.dirSync().name; +const tarGzName = 'meteor.tar.gz'; +const tarName = 'meteor.tar'; + +// This file only exists while files are being extracted, and is removed after +// the extraction succeeds. If it still exists, there is either another instance of +// the installer running, or it failed the last time it extracted files. +if (fs.existsSync(startedPath)) { + console.log('It seems the previous installation of Meteor did not succeed.'); + uninstall(); + console.log(''); +} else if (fs.existsSync(meteorPath) ) { + console.log('Meteor is already installed at', meteorPath); + console.log('If you want to reinstall, delete that folder and run this command again'); + process.exit(); +} + +// Creating symlinks requires running as an administrator or +// for developer mode to be enabled +let canCreateSymlinks = false; +try { + const target = path.resolve(tempPath, 'test-target.txt'); + const symlinkPath = path.resolve(tempPath, 'symlink.txt'); + + fs.writeFileSync(target, ''); + fs.symlinkSync(target, symlinkPath, 'file'); + + fs.unlinkSync(symlinkPath) + fs.unlinkSync(target) + canCreateSymlinks = true; +} catch (e) { + if (e.code === 'EPERM') { + // Leave canCreateSymlinks as false + } else { + console.error('Unable to check if able to create symlinks'); + console.error(e); + console.log('Assuming unable to create symlinks'); + } +} + +download(); + +function download() { + const start = Date.now(); + const downloadProgress = new cliProgress.SingleBar({ + format: 'Downloading |{bar}| {percentage}%', + clearOnComplete: true, + }, cliProgress.Presets.shades_classic); + downloadProgress.start(100, 0); + + const url = `https://packages.meteor.com/bootstrap-link?arch=os.windows.x86_64&release=${release}` + const dl = new DownloaderHelper(url, tempPath, { + retry: { maxRetries: 5, delay: 5000 }, + override: true, + fileName: tarGzName + }); + + dl.on('progress', ({ progress }) => { + downloadProgress.update(progress) + }); + dl.on('end', () => { + downloadProgress.update(100); + downloadProgress.stop(); + const end = Date.now(); + console.log(`=> Meteor Downloaded in ${(end - start) / 1000}s`); + + const exists = fs.existsSync(path.resolve(tempPath, tarGzName)) + if (!exists) { + throw new Error('meteor.tar.gz does not exist'); + } + + decompress(); + }); + + dl.start(); +} + +function decompress() { + const start = Date.now(); + const decompressProgress = new cliProgress.SingleBar({ + format: 'Decompressing |{bar}| {percentage}%', + clearOnComplete: true, + }, cliProgress.Presets.shades_classic); + decompressProgress.start(100, 0); + + const myStream = Seven.extract(path.resolve(tempPath, tarGzName), tempPath, { + $progress: true, + $bin: sevenBin.path7za, + }); + myStream.on('progress', function (progress) { + decompressProgress.update(progress.percent) + }); + + myStream.on('end', function () { + decompressProgress.update(100); + decompressProgress.stop(); + const end = Date.now(); + console.log(`=> Meteor Decompressed in ${(end - start) / 1000}s`); + extract(); + }); +} + +async function extract() { + const start = Date.now(); + fs.writeFileSync(startedPath, 'Meteor install started'); + + const decompressProgress = new cliProgress.SingleBar({ + format: 'Extracting |{bar}| {percentage}% - {fileCount} files completed', + clearOnComplete: true, + }, cliProgress.Presets.shades_classic); + decompressProgress.start(100, 0, { + fileCount: 0 + }); + + let tarPath = path.resolve(tempPath, tarName); + // 7Zip is ~15% faster, but doesn't work when the user doesn't have permission to create symlinks + // TODO: we could always use 7zip if we have it ignore the symlinks, and then manually create them as + // is done in extractWithTar + if (canCreateSymlinks) { + await extractWith7Zip(tarPath, extractPath, ({ percent, fileCount }) => { + decompressProgress.update(percent, { fileCount }) + }); + } else { + await extractWithTar(tarPath, extractPath, ({ percent, fileCount }) => { + decompressProgress.update(percent, { fileCount }) + }); + } + + decompressProgress.stop(); + const end = Date.now(); + console.log(`=> Meteor Extracted ${(end - start) / 1000}s`); + fs.unlinkSync(startedPath); + showGettingStarted(); +} + +function showGettingStarted() { + const message = ` +*************************************** + +Meteor has been installed! + +To get started fast: + + $ meteor create ~/my_cool_app + $ cd ~/my_cool_app + $ meteor + +Or see the docs at: + + docs.meteor.com + +Deploy and host your app with Cloud: + + www.meteor.com/cloud + +*************************************** + `; + + console.log(message); +} diff --git a/npm-packages/meteor-installer/meteor.bat b/npm-packages/meteor-installer/meteor.bat new file mode 100644 index 0000000000..78c38bf709 --- /dev/null +++ b/npm-packages/meteor-installer/meteor.bat @@ -0,0 +1,6 @@ +@echo off +SETLOCAL +SET METEOR_INSTALLATION=%LOCALAPPDATA%\.meteor +"%METEOR_INSTALLATION%\meteor.bat" %* +ENDLOCAL +EXIT /b %ERRORLEVEL% diff --git a/npm-packages/meteor-installer/package.json b/npm-packages/meteor-installer/package.json new file mode 100644 index 0000000000..d1829d7c1b --- /dev/null +++ b/npm-packages/meteor-installer/package.json @@ -0,0 +1,24 @@ +{ + "name": "meteor", + "version": "2.1.0", + "description": "Install Meteor on Windows", + "main": "install.js", + "scripts": { + "install": "node cli.js install" + }, + "author": "zodern", + "license": "MIT", + "dependencies": { + "7zip-bin": "^5.0.3", + "cli-progress": "^3.5.0", + "node-7z": "^2.0.5", + "node-downloader-helper": "^1.0.11", + "rimraf": "^3.0.2", + "tar": "^6.1.0", + "tmp": "^0.1.0" + }, + "bin": { + "meteor": "meteor.bat", + "meteor-installer": "cli.js" + } +} diff --git a/npm-packages/meteor-installer/uninstall.js b/npm-packages/meteor-installer/uninstall.js new file mode 100644 index 0000000000..7f098c96fa --- /dev/null +++ b/npm-packages/meteor-installer/uninstall.js @@ -0,0 +1,20 @@ +const { meteorPath } = require('./config.js'); +const rimraf = require('rimraf'); + +function uninstall() { + console.log(`Uninstalling Meteor from ${meteorPath}`); + + try { + rimraf.sync(meteorPath) + } catch (err) { + console.log('Encountered error while uninstalling:'); + console.error(err); + process.exit(1); + } + + console.log('Successfully uninstalled Meteor'); +} + +module.exports = { + uninstall +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..50e68285ab --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4646 @@ +{ + "name": "meteor", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.52.tgz", + "integrity": "sha1-GSSDv6DR5GfBAVccIQKcy3SvKAE=", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.52" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.52.tgz", + "integrity": "sha1-JpaPEvrYGM2XTISbKGtDfh6MzZE=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.52", + "jsesc": "^2.5.1", + "lodash": "^4.17.5", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.52.tgz", + "integrity": "sha1-qGelj/VxsldysteZsyhmBYVzxFA=", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.52", + "@babel/template": "7.0.0-beta.52", + "@babel/types": "7.0.0-beta.52" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.52.tgz", + "integrity": "sha1-HAzaWOC3X0XpLq+9j+GJpO7pK3Q=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.52" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.52.tgz", + "integrity": "sha1-SqxPMOpjhK82duBLUkZydjLkYN8=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.52" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.52.tgz", + "integrity": "sha1-7ySTFDLwYVXnvDnNuKaze0oos9A=", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" + } + }, + "@babel/parser": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.52.tgz", + "integrity": "sha1-TpNbYs2b+HK9N7zx9j2C/nsCN6I=", + "dev": true + }, + "@babel/runtime": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz", + "integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.12.13.tgz", + "integrity": "sha512-8fSpqYRETHATtNitsCXq8QQbKJP31/KnDl2Wz2Vtui9nKzjss2ysuZtyVsWjBtvkeEFo346gkwjYPab1hvrXkQ==", + "dev": true, + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.52.tgz", + "integrity": "sha1-ROGPrDglH1f5JRHWdI8JWrAvmW4=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.52", + "@babel/parser": "7.0.0-beta.52", + "@babel/types": "7.0.0-beta.52", + "lodash": "^4.17.5" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.52.tgz", + "integrity": "sha1-m4uplPcmTZhHhYrS/uzCc4xeLvM=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.52", + "@babel/generator": "7.0.0-beta.52", + "@babel/helper-function-name": "7.0.0-beta.52", + "@babel/helper-split-export-declaration": "7.0.0-beta.52", + "@babel/parser": "7.0.0-beta.52", + "@babel/types": "7.0.0-beta.52", + "debug": "^3.1.0", + "globals": "^11.1.0", + "invariant": "^2.2.0", + "lodash": "^4.17.5" + } + }, + "@babel/types": { + "version": "7.0.0-beta.52", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.52.tgz", + "integrity": "sha1-o+ViCxU0slOlCrzyIitSDiOxbaI=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.5", + "to-fast-properties": "^2.0.0" + } + }, + "@meteorjs/eslint-config-meteor": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@meteorjs/eslint-config-meteor/-/eslint-config-meteor-1.0.5.tgz", + "integrity": "sha1-iMFN+7Si+iJY//SInM2N3Q7MsEs=", + "dev": true + }, + "@quave/eslint-config-quave": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@quave/eslint-config-quave/-/eslint-config-quave-1.0.3.tgz", + "integrity": "sha512-acFcwHYu22Q900BHMjswu/qZDDWgtXGlXSJljSoohanG2iyOcpSKDo5KwR1MUAI3HelGfvTNGlcdrYS4veFWfQ==", + "dev": true, + "requires": { + "@meteorjs/eslint-config-meteor": "^1.0.5", + "babel-eslint": "^9.0.0-beta.3", + "eslint": "^5.6.0", + "eslint-config-airbnb": "^17.1.0", + "eslint-config-prettier": "^3.1.0", + "eslint-import-resolver-meteor": "^0.4.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-jest": "^21.26.2", + "eslint-plugin-jsx-a11y": "^6.1.1", + "eslint-plugin-meteor": "^5.1.0", + "eslint-plugin-react": "^7.11.1", + "eslint-plugin-react-hooks": "^3.0.0", + "husky": "^3.1.0", + "lint-staged": "7.3.0", + "prettier-eslint": "^8.8.2" + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-includes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", + "is-string": "^1.0.5" + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "axe-core": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.2.tgz", + "integrity": "sha512-V+Nq70NxKhYt89ArVcaNL9FDryB3vQOd+BFXZIfO3RP6rwtj+2yqqqdHEkacutglPaZLkJeuXKCjCJDMGPtPqg==", + "dev": true + }, + "axobject-query": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "9.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-9.0.0-beta.3.tgz", + "integrity": "sha512-niiSqeVysX9Hr3KjCzqz8XEQmVKeqQV7Xf2uaOyCMl6Z88IyE3k3ofXBMcEO0B8ATFHgc73Dfyx9hUaddDplag==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.52", + "@babel/parser": "7.0.0-beta.52", + "@babel/traverse": "7.0.0-beta.52", + "@babel/types": "7.0.0-beta.52", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, + "core-js-pure": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.3.tgz", + "integrity": "sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.1", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/highlight": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "eslint-config-airbnb": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.1.tgz", + "integrity": "sha512-xCu//8a/aWqagKljt+1/qAM62BYZeNq04HmdevG5yUGWpja0I/xhqd6GdLRch5oetEGFiJAnvtGuTEAese53Qg==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^13.2.0", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-config-airbnb-base": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.2.0.tgz", + "integrity": "sha512-1mg/7eoB4AUeB0X1c/ho4vb2gYkNH8Trr/EgCT/aGmKhhG+F6vF5s8+iRBlWAzFIAphxIdp3YfEKgEl0f9Xg+w==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.5", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-config-prettier": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz", + "integrity": "sha512-ixJ4U3uTLXwJts4rmSVW/lMXjlGwCijhBJHk8iVqKKSifeI0qgFEfWl8L63isfc8Od7EiBALF6BX3jKLluf/jQ==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-import-resolver-meteor": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-meteor/-/eslint-import-resolver-meteor-0.4.0.tgz", + "integrity": "sha1-yGhjhAghIIz4EzxczlGQnCamFWk=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "resolve": "^1.1.6" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-jest": { + "version": "21.27.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-21.27.2.tgz", + "integrity": "sha512-0E4OIgBJVlAmf1KfYFtZ3gYxgUzC5Eb3Jzmrc9ikI1OY+/cM8Kh72Ti7KfpeHNeD3HJNf9SmEfmvQLIz44Hrhw==", + "dev": true + }, + "eslint-plugin-jsx-a11y": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", + "integrity": "sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.11.2", + "aria-query": "^4.2.2", + "array-includes": "^3.1.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.0.2", + "axobject-query": "^2.2.0", + "damerau-levenshtein": "^1.0.6", + "emoji-regex": "^9.0.0", + "has": "^1.0.3", + "jsx-ast-utils": "^3.1.0", + "language-tags": "^1.0.5" + }, + "dependencies": { + "emoji-regex": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.1.tgz", + "integrity": "sha512-117l1H6U4X3Krn+MrzYrL57d5H7siRHWraBs7s+LjRuFK7Fe7hJqnJ0skWlinqsycVLU5YAo6L8CsEYQ0V5prg==", + "dev": true + } + } + }, + "eslint-plugin-meteor": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-meteor/-/eslint-plugin-meteor-5.2.0.tgz", + "integrity": "sha512-bHzs/0BwHdKcBbX7tYrSnBaMG+1i2f1wy8k6H/sBBsERD/yifmBUrNLiPyZkIvyVUeI8OaZw8U9fsMvLP5GhIg==", + "dev": true, + "requires": { + "invariant": "2.2.4" + } + }, + "eslint-plugin-react": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz", + "integrity": "sha512-EjxTHxjLKIBWFgDJdhKKzLh5q+vjTFrqNZX36uIxWS4OfyXe5DawqPj3U5qeJ1ngLwatjzQnmR0Lz0J0YH3kxw==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "husky": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", + "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "ci-info": "^2.0.0", + "cosmiconfig": "^5.2.1", + "execa": "^1.0.0", + "get-stdin": "^7.0.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "read-pkg": "^5.2.0", + "run-node": "^1.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/highlight": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-validate": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "leven": "^2.1.0", + "pretty-format": "^23.6.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "requires": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "language-subtag-registry": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", + "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", + "dev": true + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", + "dev": true, + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "lint-staged": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.3.0.tgz", + "integrity": "sha512-AXk40M9DAiPi7f4tdJggwuKIViUplYtVj1os1MVEteW7qOkU50EOehayCfO9TsoGK24o/EsWb41yrEgfJDDjCw==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.0.2", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "execa": "^0.9.0", + "find-parent-dir": "^0.3.0", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "jest-validate": "^23.5.0", + "listr": "^0.14.1", + "lodash": "^4.17.5", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.1", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", + "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + } + }, + "loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "dev": true + }, + "loglevel-colored-level-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", + "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "loglevel": "^1.4.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", + "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", + "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "prettier-eslint": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-8.8.2.tgz", + "integrity": "sha512-2UzApPuxi2yRoyMlXMazgR6UcH9DKJhNgCviIwY3ixZ9THWSSrUww5vkiZ3C48WvpFl1M1y/oU63deSy1puWEA==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "common-tags": "^1.4.0", + "dlv": "^1.1.0", + "eslint": "^4.0.0", + "indent-string": "^3.2.0", + "lodash.merge": "^4.6.0", + "loglevel-colored-level-prefix": "^1.0.0", + "prettier": "^1.7.0", + "pretty-format": "^23.0.1", + "require-relative": "^0.8.7", + "typescript": "^2.5.1", + "typescript-eslint-parser": "^16.0.0", + "vue-eslint-parser": "^2.0.2" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } + } + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "dependencies": { + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "staged-git-files": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.1.tgz", + "integrity": "sha512-H89UNKr1rQJvI1c/PIR3kiAMBV23yvR7LItZiV74HWZwzt7f3YHuujJ9nJZlt58WlFox7XQsOahexwk7nTe69A==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", + "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3" + } + }, + "string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + }, + "typescript-eslint-parser": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz", + "integrity": "sha512-IKawLTu4A2xN3aN/cPLxvZ0bhxZHILGDKTZWvWNJ3sLNhJ3PjfMEDQmR2VMpdRPrmWOadgWXRwjLBzSA8AGsaQ==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vue-eslint-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", + "integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..e4aee9c893 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "meteor", + "version": "0.0.1", + "description": "Used to apply Prettier and ESLint manually", + "repository": { + "type": "git", + "url": "git+https://github.com/meteor/meteor.git" + }, + "author": "Filipe Névola", + "license": "MIT", + "bugs": { + "url": "https://github.com/meteor/meteor/issues" + }, + "homepage": "https://github.com/meteor/meteor#readme", + "devDependencies": { + "@quave/eslint-config-quave": "^1.0.3" + }, + "eslintConfig": { + "extends": [ + "@quave/quave" + ] + } +} diff --git a/packages/accounts-base/accounts_server.js b/packages/accounts-base/accounts_server.js index eeea919ae5..13ac0c3ea8 100644 --- a/packages/accounts-base/accounts_server.js +++ b/packages/accounts-base/accounts_server.js @@ -4,6 +4,7 @@ import { EXPIRE_TOKENS_INTERVAL_MS, CONNECTION_CLOSE_DELAY_MS } from './accounts_common.js'; +import { URL } from 'meteor/url'; const hasOwn = Object.prototype.hasOwnProperty; @@ -37,6 +38,18 @@ export class AccountsServer extends AccountsCommon { loggedInUser: ['profile', 'username', 'emails'], otherUsers: ['profile', 'username'] }; + + // use object to keep the reference when used in functions + // where _defaultPublishFields is destructured into lexical scope + // for publish callbacks that need `this` + this._defaultPublishFields = { + projection: { + profile: 1, + username: 1, + emails: 1, + } + }; + this._initServerPublications(); // connectionId -> {connection, loginToken} @@ -66,14 +79,25 @@ export class AccountsServer extends AccountsCommon { this._skipCaseInsensitiveChecksForTest = {}; - // XXX These should probably not actually be public? this.urls = { - resetPassword: token => Meteor.absoluteUrl(`#/reset-password/${token}`), - verifyEmail: token => Meteor.absoluteUrl(`#/verify-email/${token}`), - enrollAccount: token => Meteor.absoluteUrl(`#/enroll-account/${token}`), + resetPassword: (token, extraParams) => this.buildEmailUrl(`#/reset-password/${token}`, extraParams), + verifyEmail: (token, extraParams) => this.buildEmailUrl(`#/verify-email/${token}`, extraParams), + enrollAccount: (token, extraParams) => this.buildEmailUrl(`#/enroll-account/${token}`, extraParams), }; this.addDefaultRateLimit(); + + this.buildEmailUrl = (path, extraParams = {}) => { + const url = new URL(Meteor.absoluteUrl(path)); + const params = Object.entries(extraParams); + if (params.length > 0) { + // Add additional parameters to the url + for (const [key, value] of params) { + url.searchParams.append(key, value); + } + } + return url.toString(); + }; } /// @@ -691,7 +715,7 @@ export class AccountsServer extends AccountsCommon { _initServerPublications() { // Bring into lexical scope for publish callbacks that need `this` - const { users, _autopublishFields } = this; + const { users, _autopublishFields, _defaultPublishFields } = this; // Publish all login service configuration fields other than secret. this._server.publish("meteor.loginServiceConfiguration", () => { @@ -699,22 +723,22 @@ export class AccountsServer extends AccountsCommon { return ServiceConfiguration.configurations.find({}, {fields: {secret: 0}}); }, {is_auto: true}); // not techincally autopublish, but stops the warning. - // Publish the current user's record to the client. - this._server.publish(null, function () { - if (this.userId) { - return users.find({ - _id: this.userId - }, { - fields: { - profile: 1, - username: 1, - emails: 1 - } - }); - } else { - return null; - } - }, /*suppress autopublish warning*/{is_auto: true}); + // Use Meteor.startup to give other packages a chance to call + // setDefaultPublishFields. + Meteor.startup(() => { + // Publish the current user's record to the client. + this._server.publish(null, function () { + if (this.userId) { + return users.find({ + _id: this.userId + }, { + fields: _defaultPublishFields.projection, + }); + } else { + return null; + } + }, /*suppress autopublish warning*/{is_auto: true}); + }); // Use Meteor.startup to give other packages a chance to call // addAutopublishFields. @@ -762,6 +786,14 @@ export class AccountsServer extends AccountsCommon { this._autopublishFields.otherUsers, opts.forOtherUsers); }; + // Replaces the fields to be automatically + // published when the user logs in + // + // @param {MongoFieldSpecifier} fields Dictionary of fields to return or exclude. + setDefaultPublishFields(fields) { + this._defaultPublishFields.projection = fields; + }; + /// /// ACCOUNT DATA /// diff --git a/packages/accounts-base/accounts_tests.js b/packages/accounts-base/accounts_tests.js index fa52871a21..b711bc9a9c 100644 --- a/packages/accounts-base/accounts_tests.js +++ b/packages/accounts-base/accounts_tests.js @@ -1,3 +1,7 @@ +import { URL } from 'meteor/url'; +import { Meteor } from 'meteor/meteor'; +import { Accounts } from 'meteor/accounts-base'; + Meteor.methods({ getCurrentLoginToken: function () { return Accounts._getLoginToken(this.connection.id); @@ -664,3 +668,21 @@ Tinytest.add( Accounts._beforeExternalLoginHook = null; } ); + +if(Meteor.isServer) { + Tinytest.add( + 'accounts - make sure that extra params to accounts urls are added', + test => { + // No extra params + const verifyEmailURL = new URL(Accounts.urls.verifyEmail('test')); + test.equal(verifyEmailURL.searchParams.toString(), ""); + + // Extra params + const extraParams = { test: 'success'}; + const resetPasswordURL = new URL(Accounts.urls.resetPassword('test', extraParams)); + test.equal(resetPasswordURL.searchParams.get('test'), extraParams.test); + const enrollAccountURL = new URL(Accounts.urls.enrollAccount('test', extraParams)); + test.equal(enrollAccountURL.searchParams.get('test'), extraParams.test); + } + ); +} \ No newline at end of file diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index d5df2e69c5..09094a0891 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.7.0", + version: "1.8.0", }); Package.onUse(api => { @@ -13,6 +13,7 @@ Package.onUse(api => { api.use('ejson', 'server'); api.use('callback-hook', ['client', 'server']); api.use('reactive-var', 'client'); + api.use('url', ['client', 'server']); // use unordered to work around a circular dependency // (service-configuration needs Accounts.connection) @@ -27,7 +28,7 @@ Package.onUse(api => { // If the 'blaze' package is loaded, we'll define some helpers like // {{currentUser}}. If not, no biggie. - api.use('blaze', 'client', {weak: true}); + api.use('blaze@2.3.4', 'client', {weak: true}); // Allow us to detect 'autopublish', and publish some Meteor.users fields if // it's loaded. diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index 245921ed2e..c5656d6990 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -5,7 +5,7 @@ Package.describe({ // 2.2.x in the future. The version was also bumped to 2.0.0 temporarily // during the Meteor 1.5.1 release process, so versions 2.0.0-beta.2 // through -beta.5 and -rc.0 have already been published. - version: "1.6.2" + version: "1.7.0" }); Package.onUse(api => { diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js index bfcc817710..2076985362 100644 --- a/packages/accounts-password/password_server.js +++ b/packages/accounts-password/password_server.js @@ -74,7 +74,7 @@ const getRoundsFromBcryptHash = hash => { // `password.digest`). // // The user parameter needs at least user._id and user.services -Accounts._checkPasswordUserFields = {_id: 1, services: 1}, +Accounts._checkPasswordUserFields = {_id: 1, services: 1}; // Accounts._checkPassword = (user, password) => { const result = { @@ -760,13 +760,14 @@ Accounts.generateOptionsForEmail = (email, user, url, reason) => { * @param {String} userId The id of the user to send email to. * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list. * @param {Object} [extraTokenData] Optional additional data to be added into the token record. + * @param {Object} [extraParams] Optional additional params to be added to the reset url. * @returns {Object} Object with {email, user, token, url, options} values. * @importFromPackage accounts-base */ -Accounts.sendResetPasswordEmail = (userId, email, extraTokenData) => { +Accounts.sendResetPasswordEmail = (userId, email, extraTokenData, extraParams) => { const {email: realEmail, user, token} = Accounts.generateResetToken(userId, email, 'resetPassword', extraTokenData); - const url = Accounts.urls.resetPassword(token); + const url = Accounts.urls.resetPassword(token, extraParams); const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'resetPassword'); Email.send(options); if (Meteor.isDevelopment) { @@ -789,13 +790,14 @@ Accounts.sendResetPasswordEmail = (userId, email, extraTokenData) => { * @param {String} userId The id of the user to send email to. * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first email in the list. * @param {Object} [extraTokenData] Optional additional data to be added into the token record. + * @param {Object} [extraParams] Optional additional params to be added to the enrollment url. * @returns {Object} Object with {email, user, token, url, options} values. * @importFromPackage accounts-base */ -Accounts.sendEnrollmentEmail = (userId, email, extraTokenData) => { +Accounts.sendEnrollmentEmail = (userId, email, extraTokenData, extraParams) => { const {email: realEmail, user, token} = Accounts.generateResetToken(userId, email, 'enrollAccount', extraTokenData); - const url = Accounts.urls.enrollAccount(token); + const url = Accounts.urls.enrollAccount(token, extraParams); const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'enrollAccount'); Email.send(options); if (Meteor.isDevelopment) { @@ -902,17 +904,19 @@ Meteor.methods({resetPassword: function (...args) { * @param {String} userId The id of the user to send email to. * @param {String} [email] Optional. Which address of the user's to send the email to. This address must be in the user's `emails` list. Defaults to the first unverified email in the list. * @param {Object} [extraTokenData] Optional additional data to be added into the token record. + * @param {Object} [extraParams] Optional additional params to be added to the verification url. + * * @returns {Object} Object with {email, user, token, url, options} values. * @importFromPackage accounts-base */ -Accounts.sendVerificationEmail = (userId, email, extraTokenData) => { +Accounts.sendVerificationEmail = (userId, email, extraTokenData, extraParams) => { // XXX Also generate a link using which someone can delete this // account if they own said address but weren't those who created // this account. const {email: realEmail, user, token} = Accounts.generateVerificationToken(userId, email, extraTokenData); - const url = Accounts.urls.verifyEmail(token); + const url = Accounts.urls.verifyEmail(token, extraParams); const options = Accounts.generateOptionsForEmail(realEmail, user, url, 'verifyEmail'); Email.send(options); if (Meteor.isDevelopment) { @@ -1155,18 +1159,7 @@ Meteor.methods({createUser: function (...args) { error: new Meteor.Error(403, "Signups forbidden") }; - // Create user. result contains id and token. - const userId = createUser(options); - // safety belt. createUser is supposed to throw on error. send 500 error - // instead of sending a verification email with empty userid. - if (! userId) - throw new Error("createUser failed to insert new user"); - - // If `Accounts._options.sendVerificationEmail` is set, register - // a token to verify the user's primary email, and send it to - // that address. - if (options.email && Accounts._options.sendVerificationEmail) - Accounts.sendVerificationEmail(userId, options.email); + const userId = Accounts.createUserVerifyingEmail(options); // client gets logged in as the new user afterwards. return {userId: userId}; @@ -1174,6 +1167,43 @@ Meteor.methods({createUser: function (...args) { ); }}); +/** + * @summary Creates an user and sends an email if `options.email` is informed. + * Then if the `sendVerificationEmail` option from the `Accounts` package is + * enabled, you'll send a verification email if `options.password` is informed, + * otherwise you'll send an enrollment email. + * @locus Server + * @param {Object} options The options object to be passed down when creating + * the user + * @param {String} options.username A unique name for this user. + * @param {String} options.email The user's email address. + * @param {String} options.password The user's password. This is __not__ sent in plain text over the wire. + * @param {Object} options.profile The user's profile, typically including the `name` field. + * @importFromPackage accounts-base + * */ +Accounts.createUserVerifyingEmail = (options) => { + options = { ...options }; + // Create user. result contains id and token. + const userId = createUser(options); + // safety belt. createUser is supposed to throw on error. send 500 error + // instead of sending a verification email with empty userid. + if (! userId) + throw new Error("createUser failed to insert new user"); + + // If `Accounts._options.sendVerificationEmail` is set, register + // a token to verify the user's primary email, and send it to + // that address. + if (options.email && Accounts._options.sendVerificationEmail) { + if (options.password) { + Accounts.sendVerificationEmail(userId, options.email); + } else { + Accounts.sendEnrollmentEmail(userId, options.email); + } + } + + return userId; +}; + // Create user directly on the server. // // Unlike the client version, this does not log you in as this user diff --git a/packages/accounts-password/password_tests.js b/packages/accounts-password/password_tests.js index 2776efbb0d..207982e894 100644 --- a/packages/accounts-password/password_tests.js +++ b/packages/accounts-password/password_tests.js @@ -1966,4 +1966,25 @@ if (Meteor.isServer) (() => { } ); + Tinytest.add('passwords - extra params in email urls', (test) => { + const username = Random.id(); + const email = `${username}-intercept@example.com`; + + const userId = Accounts.createUser({ + username: username, + email: email + }); + + const extraParams = { test: 'success' }; + Accounts.sendEnrollmentEmail(userId, email, null, extraParams); + + const enrollPasswordEmailOptions = + Meteor.call("getInterceptedEmails", email)[0]; + + const re = new RegExp(`${Meteor.absoluteUrl()}(\\S*)`); + const match = enrollPasswordEmailOptions.text.match(re); + const url = new URL(match) + test.equal(url.searchParams.get('test'), extraParams.test); + }); + }) (); diff --git a/packages/accounts-ui-unstyled/login_buttons_dropdown.js b/packages/accounts-ui-unstyled/login_buttons_dropdown.js index 3ec72f0dd8..2594d3358e 100644 --- a/packages/accounts-ui-unstyled/login_buttons_dropdown.js +++ b/packages/accounts-ui-unstyled/login_buttons_dropdown.js @@ -238,8 +238,10 @@ Template._loginButtonsLoggedOutDropdown.events({ }, 'keypress #forgot-password-email': event => { - if (event.keyCode === 13) + if (event.keyCode === 13) { + event.preventDefault(); forgotPassword(); + } }, 'click #login-buttons-forgot-password': forgotPassword, @@ -335,10 +337,6 @@ Template._loginButtonsLoggedOutDropdown.events({ if (password !== null) document.getElementById('login-password').value = password; }, - 'keypress #login-username, keypress #login-email, keypress #login-username-or-email, keypress #login-password, keypress #login-password-again': event => { - if (event.keyCode === 13) - loginOrSignup(); - } }); Template._loginButtonsLoggedOutDropdown.helpers({ diff --git a/packages/accounts-ui-unstyled/package.js b/packages/accounts-ui-unstyled/package.js index f8e42f0ec3..6f5f767058 100644 --- a/packages/accounts-ui-unstyled/package.js +++ b/packages/accounts-ui-unstyled/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Unstyled version of login widgets", - version: "1.4.2" + version: "1.4.3" }); Package.onUse(function (api) { diff --git a/packages/accounts-ui/package.js b/packages/accounts-ui/package.js index 81d2b398a8..6cbba924cc 100644 --- a/packages/accounts-ui/package.js +++ b/packages/accounts-ui/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Simple templates to add login widgets to an app", - version: "1.3.1", + version: "1.3.2", }); Package.onUse(api => { diff --git a/packages/autoupdate/autoupdate_server.js b/packages/autoupdate/autoupdate_server.js index ef564fc8ef..57f81de196 100644 --- a/packages/autoupdate/autoupdate_server.js +++ b/packages/autoupdate/autoupdate_server.js @@ -2,15 +2,18 @@ // (web.browser, web.browser.legacy, web.cordova). When a client observes // a change in the versions associated with its client architecture, // it will refresh itself, either by swapping out CSS assets or by -// reloading the page. +// reloading the page. Changes to the replaceable version are ignored +// and handled by the hot-module-replacement package. // -// There are three versions for any given client architecture: `version`, -// `versionRefreshable`, and `versionNonRefreshable`. The refreshable -// version is a hash of just the client resources that are refreshable, -// such as CSS, while the non-refreshable version is a hash of the rest of -// the client assets, excluding the refreshable ones: HTML, JS, and static -// files in the `public` directory. The `version` version is a combined -// hash of everything. +// There are four versions for any given client architecture: `version`, +// `versionRefreshable`, `versionNonRefreshable`, and +// `versionReplaceable`. The refreshable version is a hash of just the +// client resources that are refreshable, such as CSS. The replaceable +// version is a hash of files that can be updated with HMR. The +// non-refreshable version is a hash of the rest of the client assets, +// excluding the refreshable ones: HTML, JS that is not replaceable, and +// static files in the `public` directory. The `version` version is a +// combined hash of everything. // // If the environment variable `AUTOUPDATE_VERSION` is set, it will be // used in place of all client versions. You can use this variable to @@ -75,6 +78,8 @@ function updateVersions(shouldReloadClientProgram) { WebApp.calculateClientHashRefreshable(arch), versionNonRefreshable: AUTOUPDATE_VERSION || WebApp.calculateClientHashNonRefreshable(arch), + versionReplaceable: AUTOUPDATE_VERSION || + WebApp.calculateClientHashReplaceable(arch) }; }); diff --git a/packages/autoupdate/package.js b/packages/autoupdate/package.js index e4a2bf47e6..d3c117374e 100644 --- a/packages/autoupdate/package.js +++ b/packages/autoupdate/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Update the client when new client code is available", - version: '1.6.0' + version: '1.7.0' }); Package.onUse(function (api) { diff --git a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json index 9705d36cb7..32c0d2c752 100644 --- a/packages/babel-compiler/.npm/package/npm-shrinkwrap.json +++ b/packages/babel-compiler/.npm/package/npm-shrinkwrap.json @@ -2,181 +2,171 @@ "lockfileVersion": 1, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==" }, "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", "dependencies": { "json5": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.2.tgz", - "integrity": "sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==" } } }, "@babel/generator": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", - "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==" }, "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz", + "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==" }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", - "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==" - }, - "@babel/helper-builder-react-jsx": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz", - "integrity": "sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw==" - }, - "@babel/helper-builder-react-jsx-experimental": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.0.tgz", - "integrity": "sha512-3xJEiyuYU4Q/Ar9BsHisgdxZsRlsShMe90URZ0e6przL26CCs8NJbDoxH94kKT17PcxlMhsCAwZd90evCo26VQ==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==" }, "@babel/helper-create-class-features-plugin": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz", - "integrity": "sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==" }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", - "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==" + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz", + "integrity": "sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==" }, "@babel/helper-define-map": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", - "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==" + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==" }, "@babel/helper-explode-assignable-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", - "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", + "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==" }, "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==" }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==" }, "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==" + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==" }, "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==" + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==" }, "@babel/helper-module-transforms": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", - "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==" }, "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==" }, "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" - }, - "@babel/helper-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", - "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, "@babel/helper-remap-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", - "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", + "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==" }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==" }, "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==" + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==" }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==" }, "@babel/helper-validator-identifier": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", - "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" }, "@babel/helper-wrap-function": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", - "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==" + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", + "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==" }, "@babel/helpers": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", - "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==" + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==" }, "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==" }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", - "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==" }, "@babel/plugin-proposal-class-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", - "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==" }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==" }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.0.tgz", - "integrity": "sha512-UgqBv6bjq4fDb8uku9f+wcm1J7YxJ5nT7WO/jBr0cl0PLKb7t1O6RNR1kZbjgx2LQtsDI9hwoQVmn0yhXeQyow==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==" }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==" }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", - "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==" + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz", + "integrity": "sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==" }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -184,9 +174,9 @@ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" }, "@babel/plugin-syntax-class-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz", - "integrity": "sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==" }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", @@ -194,9 +184,9 @@ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" }, "@babel/plugin-syntax-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", - "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==" }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", @@ -219,169 +209,164 @@ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" }, "@babel/plugin-transform-arrow-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", - "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==" }, "@babel/plugin-transform-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", - "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==" }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", - "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==" }, "@babel/plugin-transform-block-scoping": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", - "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==" }, "@babel/plugin-transform-classes": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.2.tgz", - "integrity": "sha512-TC2p3bPzsfvSsqBZo0kJnuelnoK9O3welkUpqSqBQuBF6R5MN2rysopri8kNvtlGIb2jmUO7i15IooAZJjZuMQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==" }, "@babel/plugin-transform-computed-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", - "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==" }, "@babel/plugin-transform-destructuring": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.8.tgz", - "integrity": "sha512-eRJu4Vs2rmttFCdhPUM3bV0Yo/xPSdPw6ML9KHs/bjB4bLA5HXlbvYXPOD5yASodGod+krjYx21xm1QmL8dCJQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==" }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", - "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==" }, "@babel/plugin-transform-for-of": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz", - "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==" }, "@babel/plugin-transform-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", - "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==" }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", - "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==" }, "@babel/plugin-transform-object-super": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", - "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==" }, "@babel/plugin-transform-parameters": { - "version": "7.9.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.3.tgz", - "integrity": "sha512-fzrQFQhp7mIhOzmOtPiKffvCYQSK10NR8t6BBz2yPbeUHb9OLW8RZGtgDRBn8z2hGcwvKDL3vC7ojPTLNxmqEg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==" }, "@babel/plugin-transform-property-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", - "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==" }, "@babel/plugin-transform-react-display-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", - "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz", + "integrity": "sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w==" }, "@babel/plugin-transform-react-jsx": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz", - "integrity": "sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz", + "integrity": "sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==" }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz", - "integrity": "sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz", + "integrity": "sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg==" }, - "@babel/plugin-transform-react-jsx-self": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz", - "integrity": "sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ==" - }, - "@babel/plugin-transform-react-jsx-source": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz", - "integrity": "sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw==" + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz", + "integrity": "sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg==" }, "@babel/plugin-transform-regenerator": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", - "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==" }, "@babel/plugin-transform-runtime": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz", - "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", + "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==" }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", - "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==" }, "@babel/plugin-transform-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", - "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==" }, "@babel/plugin-transform-sticky-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", - "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==" + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz", + "integrity": "sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==" }, "@babel/plugin-transform-template-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", - "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==" }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", - "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz", + "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==" }, "@babel/plugin-transform-unicode-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", - "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==" }, "@babel/preset-react": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.4.tgz", - "integrity": "sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ==" + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz", + "integrity": "sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==" }, "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==" + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==" }, "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==" + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==" }, "@babel/traverse": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", - "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==" }, "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==" + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==" }, "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" }, "acorn-dynamic-import": { "version": "4.0.0", @@ -429,9 +414,9 @@ "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==" }, "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" }, "babel-plugin-minify-builtins": { "version": "0.5.0", @@ -553,6 +538,11 @@ "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==" }, + "call-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", + "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -574,9 +564,9 @@ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==" }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==" }, "define-properties": { "version": "1.1.3", @@ -599,15 +589,25 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==" }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -634,9 +634,9 @@ "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==" }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "magic-string": { "version": "0.25.7", @@ -644,9 +644,9 @@ "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" }, "meteor-babel": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-7.9.0.tgz", - "integrity": "sha512-cJI8Mu8XG0aFh7b6I/PpgfiJV46WKp75o0hgknw9oCQ8X/HhZ8BtQIRVT7WGCirH3ATfmEqRmW00UimAQJOnhw==" + "version": "7.10.6", + "resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-7.10.6.tgz", + "integrity": "sha512-ppyHxsglz8e55N0KsCHsBFrnO/rXEubNf8PnhkQkUEfjFwFdqd4oF/uZNe99Pqa/C8+rR5Q3bMvj8zbesF1dhA==" }, "meteor-babel-helpers": { "version": "0.0.3", @@ -669,24 +669,14 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { "version": "8.2.0", @@ -694,24 +684,24 @@ "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==" }, "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regenerator-transform": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", - "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==" + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" }, "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==" + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==" }, "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { "version": "0.6.4", @@ -730,11 +720,6 @@ "resolved": "https://registry.npmjs.org/reify/-/reify-0.20.12.tgz", "integrity": "sha512-4BzKwDWyJJbukwI6xIJRh+BDTitoGzxdgYPiQQ1zbcTZW6I8xgHPw1DnVuEs/mEZQlYm1e09DcFSApb4UaR5bQ==" }, - "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==" - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -766,9 +751,9 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==" }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", diff --git a/packages/babel-compiler/babel-compiler.js b/packages/babel-compiler/babel-compiler.js index b88abe5a30..ea08fed9c0 100644 --- a/packages/babel-compiler/babel-compiler.js +++ b/packages/babel-compiler/babel-compiler.js @@ -5,8 +5,9 @@ var JSON5 = Npm.require("json5"); * Plugin.registerCompiler * @param {Object} extraFeatures The same object that getDefaultOptions takes */ -BabelCompiler = function BabelCompiler(extraFeatures) { +BabelCompiler = function BabelCompiler(extraFeatures, modifyBabelConfig) { this.extraFeatures = extraFeatures; + this.modifyBabelConfig = modifyBabelConfig; this._babelrcCache = null; this._babelrcWarnings = Object.create(null); this.cacheDirectory = null; @@ -130,6 +131,10 @@ BCp.processOneFileForTarget = function (inputFile, source) { ? "packages/" + packageName + "/" + inputFilePath : inputFilePath; + if (this.modifyBabelConfig) { + this.modifyBabelConfig(babelOptions, inputFile); + } + try { var result = profile('Babel.compile', function () { return Babel.compile(source, babelOptions, cacheOptions); diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 4534a9cb37..551ad357c3 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,11 +6,11 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '7.5.3' + version: '7.6.0' }); Npm.depends({ - 'meteor-babel': '7.9.0', + 'meteor-babel': '7.10.6', 'json5': '2.1.1' }); diff --git a/packages/boilerplate-generator/package.js b/packages/boilerplate-generator/package.js index d370abb27a..83fc175361 100644 --- a/packages/boilerplate-generator/package.js +++ b/packages/boilerplate-generator/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Generates the boilerplate html from program's manifest", - version: '1.7.0' + version: '1.7.1' }); Npm.depends({ diff --git a/packages/boilerplate-generator/template-web.cordova.js b/packages/boilerplate-generator/template-web.cordova.js index 236fb2e60f..591f3887de 100644 --- a/packages/boilerplate-generator/template-web.cordova.js +++ b/packages/boilerplate-generator/template-web.cordova.js @@ -29,7 +29,7 @@ export const headTemplate = ({ ' ', ' ', ' ', - ' ', + ' ', (headSections.length === 1) ? [cssBundle, headSections[0]].join('\n') diff --git a/packages/browser-policy-content/browser-policy-content.js b/packages/browser-policy-content/browser-policy-content.js index fd7e829e7d..4d93d0fea5 100644 --- a/packages/browser-policy-content/browser-policy-content.js +++ b/packages/browser-policy-content/browser-policy-content.js @@ -106,7 +106,7 @@ var addSourceForDirective = function (directive, src) { var toAdd = []; //Only add single quotes to CSP2 script digests - if (/^(sha(256|384|512)-)/i.test(src)) { + if (/^(sha(256|384|512)|nonce)-/i.test(src)) { toAdd.push("'" + src + "'"); } else { src = src.toLowerCase(); diff --git a/packages/browser-policy-content/package.js b/packages/browser-policy-content/package.js index 5c8f18fe01..2015ca05c2 100644 --- a/packages/browser-policy-content/package.js +++ b/packages/browser-policy-content/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Configure content security policies", - version: "1.1.0" + version: "1.1.1" }); Package.onUse(function (api) { diff --git a/packages/browser-policy/browser-policy-test.js b/packages/browser-policy/browser-policy-test.js index 19ca95c292..d898f46f6d 100644 --- a/packages/browser-policy/browser-policy-test.js +++ b/packages/browser-policy/browser-policy-test.js @@ -143,6 +143,30 @@ Tinytest.add("browser-policy - csp", function (test) { "default-src 'none'; frame-src https://foo.com; " +
 "object-src http://foo.com https://foo.com; " +
 "frame-ancestors https://foo.com;")); + + // CSP2 options: nonce + BrowserPolicy.content.disallowAll(); + BrowserPolicy.content.allowScriptOrigin('nonce-2gB8y5CrknnK2dgQk'); + test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), + "default-src 'none'; script-src 'nonce-2gB8y5CrknnK2dgQk';")); + + // CSP2 options: sha256 + BrowserPolicy.content.disallowAll(); + BrowserPolicy.content.allowScriptOrigin('sha256-KFQx9ysdKgqbAPoY7'); + test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), + "default-src 'none'; script-src 'sha256-KFQx9ysdKgqbAPoY7';")); + + // CSP2 options: sha384 + BrowserPolicy.content.disallowAll(); + BrowserPolicy.content.allowScriptOrigin('sha384-mChdKgyBF83ewvbTy'); + test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), + "default-src 'none'; script-src 'sha384-mChdKgyBF83ewvbTy';")); + + // CSP2 options: sha512 + BrowserPolicy.content.disallowAll(); + BrowserPolicy.content.allowScriptOrigin('sha512-A8x946bPwaak2LToB'); + test.isTrue(cspsEqual(BrowserPolicy.content._constructCsp(), + "default-src 'none'; script-src 'sha512-A8x946bPwaak2LToB';")); }); Tinytest.add("browser-policy - x-frame-options", function (test) { diff --git a/packages/ddp-client/package.js b/packages/ddp-client/package.js index 5e50021f99..1d5b5a5bcd 100644 --- a/packages/ddp-client/package.js +++ b/packages/ddp-client/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's latency-compensated distributed data client", - version: '2.3.3', + version: '2.4.0', documentation: null }); diff --git a/packages/http/.gitignore b/packages/deprecated/http/.gitignore similarity index 100% rename from packages/http/.gitignore rename to packages/deprecated/http/.gitignore diff --git a/packages/http/.npm/package/.gitignore b/packages/deprecated/http/.npm/package/.gitignore similarity index 100% rename from packages/http/.npm/package/.gitignore rename to packages/deprecated/http/.npm/package/.gitignore diff --git a/packages/http/.npm/package/README b/packages/deprecated/http/.npm/package/README similarity index 100% rename from packages/http/.npm/package/README rename to packages/deprecated/http/.npm/package/README diff --git a/packages/http/.npm/package/npm-shrinkwrap.json b/packages/deprecated/http/.npm/package/npm-shrinkwrap.json similarity index 100% rename from packages/http/.npm/package/npm-shrinkwrap.json rename to packages/deprecated/http/.npm/package/npm-shrinkwrap.json diff --git a/packages/http/README.md b/packages/deprecated/http/README.md similarity index 87% rename from packages/http/README.md rename to packages/deprecated/http/README.md index 01164d04de..bfbbe7311f 100644 --- a/packages/http/README.md +++ b/packages/deprecated/http/README.md @@ -2,6 +2,11 @@ [Source code of released version](https://github.com/meteor/meteor/tree/master/packages/http) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/http) *** +## Deprecated +This package has been deprecated in favor of the [fetch](https://atmospherejs.com/meteor/fetch) package and new web standards. + +## Docs + `HTTP` provides an HTTP request API on the client and server. To use these functions, add the HTTP package to your project with `$ meteor add http`. diff --git a/packages/http/httpcall_client.js b/packages/deprecated/http/httpcall_client.js similarity index 99% rename from packages/http/httpcall_client.js rename to packages/deprecated/http/httpcall_client.js index a8aac475da..c3964ac349 100644 --- a/packages/http/httpcall_client.js +++ b/packages/deprecated/http/httpcall_client.js @@ -6,6 +6,7 @@ var hasOwn = Object.prototype.hasOwnProperty; /** * @summary Perform an outbound HTTP request. * @locus Anywhere + * @deprecated * @param {String} method The [HTTP method](http://en.wikipedia.org/wiki/HTTP_method) to use, such as "`GET`", "`POST`", or "`HEAD`". * @param {String} url The URL to retrieve. * @param {Object} [options] diff --git a/packages/http/httpcall_common.js b/packages/deprecated/http/httpcall_common.js similarity index 92% rename from packages/http/httpcall_common.js rename to packages/deprecated/http/httpcall_common.js index a955ecd3d0..2114b92257 100644 --- a/packages/http/httpcall_common.js +++ b/packages/deprecated/http/httpcall_common.js @@ -1,6 +1,10 @@ var MAX_LENGTH = 500; // if you change this, also change the appropriate test var slice = Array.prototype.slice; +var deprecationMessage = function() { + Log.debug('The http package has been deprecated, please migrate to the fetch package and new web standards.'); +}; + exports.makeErrorByStatus = function(statusCode, content) { var message = "failed [" + statusCode + "]"; @@ -49,8 +53,10 @@ var HTTP = exports.HTTP = {}; * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call). * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client. * @locus Anywhere + * @deprecated */ HTTP.get = function (/* varargs */) { + deprecationMessage(); return HTTP.call.apply(this, ["GET"].concat(slice.call(arguments))); }; @@ -60,8 +66,10 @@ HTTP.get = function (/* varargs */) { * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call). * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client. * @locus Anywhere + * @deprecated */ HTTP.post = function (/* varargs */) { + deprecationMessage(); return HTTP.call.apply(this, ["POST"].concat(slice.call(arguments))); }; @@ -71,8 +79,10 @@ HTTP.post = function (/* varargs */) { * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call). * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client. * @locus Anywhere + * @deprecated */ HTTP.put = function (/* varargs */) { + deprecationMessage(); return HTTP.call.apply(this, ["PUT"].concat(slice.call(arguments))); }; @@ -82,8 +92,10 @@ HTTP.put = function (/* varargs */) { * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call). * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client. * @locus Anywhere + * @deprecated */ HTTP.del = function (/* varargs */) { + deprecationMessage(); return HTTP.call.apply(this, ["DELETE"].concat(slice.call(arguments))); }; @@ -93,7 +105,9 @@ HTTP.del = function (/* varargs */) { * @param {Object} [callOptions] Options passed on to [`HTTP.call`](#http_call). * @param {Function} [asyncCallback] Callback that is called when the request is completed. Required on the client. * @locus Anywhere + * @deprecated */ HTTP.patch = function (/* varargs */) { + deprecationMessage(); return HTTP.call.apply(this, ["PATCH"].concat(slice.call(arguments))); }; diff --git a/packages/http/httpcall_server.js b/packages/deprecated/http/httpcall_server.js similarity index 100% rename from packages/http/httpcall_server.js rename to packages/deprecated/http/httpcall_server.js diff --git a/packages/http/httpcall_tests.js b/packages/deprecated/http/httpcall_tests.js similarity index 100% rename from packages/http/httpcall_tests.js rename to packages/deprecated/http/httpcall_tests.js diff --git a/packages/http/package.js b/packages/deprecated/http/package.js similarity index 89% rename from packages/http/package.js rename to packages/deprecated/http/package.js index a106c1c6c3..fa72508abf 100644 --- a/packages/http/package.js +++ b/packages/deprecated/http/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Make HTTP calls to remote servers", - version: '1.4.2' + version: '1.4.3' }); Npm.depends({ @@ -8,12 +8,14 @@ Npm.depends({ }); Package.onUse(function (api) { + api.versionsFrom('1.12.1'); api.use([ 'url', // This package intentionally does not depend on ecmascript, so that // ecmascript and its dependencies can depend on http without creating // package dependency cycles. - 'modules' + 'modules', + 'logging' // For deprecation message ]); api.mainModule('httpcall_client.js', 'client'); diff --git a/packages/http/test_responder.js b/packages/deprecated/http/test_responder.js similarity index 100% rename from packages/http/test_responder.js rename to packages/deprecated/http/test_responder.js diff --git a/packages/http/test_static.serveme b/packages/deprecated/http/test_static.serveme similarity index 100% rename from packages/http/test_static.serveme rename to packages/deprecated/http/test_static.serveme diff --git a/packages/dev-error-overlay/README.md b/packages/dev-error-overlay/README.md new file mode 100644 index 0000000000..6f72f1f1db --- /dev/null +++ b/packages/dev-error-overlay/README.md @@ -0,0 +1,3 @@ +### dev-error-overlay + +Show build errors in client when using HMR diff --git a/packages/dev-error-overlay/client.js b/packages/dev-error-overlay/client.js new file mode 100644 index 0000000000..9712548f22 --- /dev/null +++ b/packages/dev-error-overlay/client.js @@ -0,0 +1,92 @@ +const styles = ` + .container { + all: initial; + background: #FEFEFE; + padding: 50px; + min-height: 30vh; + max-height: 100%; + width: 100%; + position: fixed; + left: 0; + top: 0; + font-family: sans-serif; + box-shadow: inset 0 0 100px #e411111f, 0 0 20px #00000085; + box-sizing: border-box; + overflow-y: auto; + } + + .section { + margin-bottom: 50px; + } + + pre { + overflow-x: auto; + } +`; + +function createSection (title, content) { + var sectionContainer = document.createElement('div'); + sectionContainer.classList.add('section'); + + var header = document.createElement('h3'); + header.textContent = title; + sectionContainer.appendChild(header); + + var message = document.createElement('pre'); + message.innerHTML = content; + sectionContainer.appendChild(message); + + return sectionContainer; +} + +let container = null; +let contentEl = null; + +function init () { + if (container) { + return; + } + + container = document.createElement('div'); + document.body.append(container); + + contentEl = document.createElement('div'); + contentEl.classList.add('container'); + + let shadow = container.attachShadow({ mode: 'open' }); + shadow.appendChild(contentEl); + + let style = document.createElement('style'); + style.textContent = styles; + shadow.appendChild(style); + + let button = document.createElement('button'); + button.textContent = 'Close'; + button.addEventListener('click', close); + contentEl.appendChild(button); +} + +function close() { + document.body.removeChild(container); + container = null; + contentEl = null; +} + +DevErrorOverlay = { + showMessage(title, message) { + init(); + + let sectionEl = createSection(title, message); + contentEl.prepend(sectionEl); + + return () => { + if (container && contentEl && sectionEl.parentNode === contentEl) { + contentEl.removeChild(sectionEl); + + if (contentEl.childNodes.length === 1) { + close(); + } + } + }; + } +} diff --git a/packages/dev-error-overlay/package.js b/packages/dev-error-overlay/package.js new file mode 100644 index 0000000000..72a362776f --- /dev/null +++ b/packages/dev-error-overlay/package.js @@ -0,0 +1,14 @@ +Package.describe({ + version: '0.1.0', + summary: 'Show build errors in client when using HMR', + documentation: 'README.md', + devOnly: true +}); + +Package.onUse(function (api) { + api.use([ + 'modules' + ]); + api.export('DevErrorOverlay', 'client'); + api.addFiles('client.js', 'modern'); +}); diff --git a/packages/dynamic-import/CHANGELOG.md b/packages/dynamic-import/CHANGELOG.md new file mode 100644 index 0000000000..a47667e724 --- /dev/null +++ b/packages/dynamic-import/CHANGELOG.md @@ -0,0 +1,8 @@ +## Changelog + +## 0.5.3 - 2020-10-02 +### Breaking changes +- N/A + +### Changes +- Supports `useLocationOrigin` and `disableLocationOriginIframe` options in the settings (`public.packages['dynamic-import']`) to allow developers to deliver dynamic imports data from different origins than `ROOT_URL`. diff --git a/packages/dynamic-import/client.js b/packages/dynamic-import/client.js index e63f14d2d6..21b112aff3 100644 --- a/packages/dynamic-import/client.js +++ b/packages/dynamic-import/client.js @@ -1,6 +1,12 @@ var Module = module.constructor; var cache = require("./cache.js"); var meteorInstall = require("meteor/modules").meteorInstall; +var dynamicVersions = require("./dynamic-versions.js"); + +var dynamicImportSettings = Meteor.settings + && Meteor.settings.public + && Meteor.settings.public.packages + && Meteor.settings.public.packages['dynamic-import'] || {}; // Call module.dynamicImport(id) to fetch a module and any/all of its // dependencies that have not already been fetched, and evaluate them as @@ -18,7 +24,6 @@ Module.prototype.dynamicImport = function (id) { meteorInstall.fetch = function (ids) { var tree = Object.create(null); var versions = Object.create(null); - var dynamicVersions = require("./dynamic-versions.js"); var missing; function addSource(id, source) { @@ -118,6 +123,14 @@ exports.setSecretKey = function (key) { var fetchURL = require("./common.js").fetchURL; +function inIframe() { + try { + return window.self !== window.top; + } catch (e) { + return true; + } +} + function fetchMissing(missingTree) { // If the hostname of the URL returned by Meteor.absoluteUrl differs // from location.host, then we'll be making a cross-origin request here, @@ -127,7 +140,18 @@ function fetchMissing(missingTree) { // preflight OPTIONS request, which may add latency to the first dynamic // import() request, so it's a good idea for ROOT_URL to match // location.host if possible, though not strictly necessary. - var url = Meteor.absoluteUrl(fetchURL); + + var url = fetchURL; + + var useLocationOrigin = dynamicImportSettings.useLocationOrigin; + + var disableLocationOriginIframe = dynamicImportSettings.disableLocationOriginIframe; + + if (useLocationOrigin && location && !(disableLocationOriginIframe && inIframe())) { + url = location.origin.concat(url); + } else { + url = Meteor.absoluteUrl(url); + } if (secretKey) { url += "key=" + secretKey; diff --git a/packages/dynamic-import/dynamic-versions.js b/packages/dynamic-import/dynamic-versions.js index 93494a9a7f..05538cc33f 100644 --- a/packages/dynamic-import/dynamic-versions.js +++ b/packages/dynamic-import/dynamic-versions.js @@ -3,6 +3,8 @@ // modules, for use in client.js and cache.js. var versions = __DYNAMIC_VERSIONS__; +const METEOR_PREFIX = '/node_modules/meteor/'; + exports.get = function (id) { var tree = versions; var version = null; @@ -66,7 +68,24 @@ function precacheOnLoad(event) { // will be fetched in one HTTP POST request. function prefetchInChunks(modules, amount) { Promise.all(modules.splice(0, amount).map(function (id) { - return module.prefetch(id); + return new Promise(function (resolve, reject) { + module.prefetch(id).then(resolve).catch( + function (err) { + // we probably have a : _ mismatch + // what can get wrong if we do the replacement + // 1. a package with a name like a_b:package will not resolve + // 2. someone falsely imports a_package that does not exist but a + // package a:package exists, so this one gets imported and its usage + // will fail + if (id.indexOf(METEOR_PREFIX) === 0) { + module.prefetch( + METEOR_PREFIX + id.replace(METEOR_PREFIX, '').replace('_', ':') + ).then(resolve).catch(reject); + } else { + reject(err); + } + }) + }); })).then(function () { if (modules.length > 0) { setTimeout(function () { diff --git a/packages/dynamic-import/package.js b/packages/dynamic-import/package.js index 6fb1edbdf3..d0b29622c3 100644 --- a/packages/dynamic-import/package.js +++ b/packages/dynamic-import/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "dynamic-import", - version: "0.5.2", + version: "0.6.0", summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax", documentation: "README.md" }); @@ -14,6 +14,7 @@ Package.onUse(function (api) { api.use("fetch"); api.use("modern-browsers"); api.use("inter-process-messaging", "server"); + api.use("hot-module-replacement", { weak: true }); api.mainModule("client.js", "client"); api.mainModule("server.js", "server"); diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 16cac4465e..1505d14f32 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,19 +1,20 @@ Package.describe({ name: 'ecmascript', - version: '0.14.3', + version: '0.15.0', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md' }); Package.registerBuildPlugin({ name: 'compile-ecmascript', - use: ['babel-compiler'], + use: ['babel-compiler', 'react-fast-refresh'], sources: ['plugin.js'] }); Package.onUse(function (api) { api.use('isobuild:compiler-plugin@1.0.0'); api.use('babel-compiler'); + api.use('react-fast-refresh'); // The following api.imply calls should match those in // ../coffeescript/package.js. diff --git a/packages/ecmascript/plugin.js b/packages/ecmascript/plugin.js index 7f6fce671a..2a64d44b98 100644 --- a/packages/ecmascript/plugin.js +++ b/packages/ecmascript/plugin.js @@ -3,5 +3,10 @@ Plugin.registerCompiler({ }, function () { return new BabelCompiler({ react: true + }, (babelOptions, file) => { + if (file.hmrAvailable() && ReactFastRefresh.babelPlugin) { + babelOptions.plugins = babelOptions.plugins || []; + babelOptions.plugins.push(ReactFastRefresh.babelPlugin); + } }); }); diff --git a/packages/email/email.js b/packages/email/email.js index c9425114fa..ed46eada8b 100644 --- a/packages/email/email.js +++ b/packages/email/email.js @@ -99,8 +99,10 @@ var smtpSend = function (transport, mail) { }; var sendHooks = []; + /** - * Hook that runs before email is sent. + * @summary Hook that runs before email is sent. + * @locus Server * * @param f {function} receives the arguments to Email.send and should return true to go * ahead and send the email (or at least, try subsequent hooks), or diff --git a/packages/facebook-oauth/.gitignore b/packages/facebook-oauth/.gitignore index 677a6fc263..3ccf4f8cd6 100644 --- a/packages/facebook-oauth/.gitignore +++ b/packages/facebook-oauth/.gitignore @@ -1 +1,2 @@ .build* +.versions diff --git a/packages/facebook-oauth/CHANGELOG.md b/packages/facebook-oauth/CHANGELOG.md new file mode 100644 index 0000000000..5fbc7693da --- /dev/null +++ b/packages/facebook-oauth/CHANGELOG.md @@ -0,0 +1,22 @@ +## Changelog + +## 1.7.3 - 2020-10-05 +### Breaking changes +- N/A + +### Changes +- Updated to `1.8` now using Facebook GraphAPI v8. + +## 1.7.2 - 2020-09-30 +### Breaking changes +- N/A + +### Changes +- Supports a new way to call the token from Facebook using a URL that is different from the ROOT_URL. With `overrideRootUrlFromStateRedirectUrl` as `true` in the settings (`packages.facebook-oauth.overrideRootUrlFromStateRedirectUrl`) we are going to use the redirect URL provided in the initial call. So the redirect URL will be used again in the server to get the token, this information will come from the state. This is important to authenticate using Facebook using different domains in the same server. + +## 1.7.1 - 2020-09-29 +### Breaking changes +- N/A + +### Changes +- Supports `params` and `absoluteUrlOptions` as options and pass along to `OAuth._redirectUri`, this is important to authenticate using Facebook using different domains in the same server. diff --git a/packages/facebook-oauth/facebook_client.js b/packages/facebook-oauth/facebook_client.js index de6241dd0f..3f6d39abff 100644 --- a/packages/facebook-oauth/facebook_client.js +++ b/packages/facebook-oauth/facebook_client.js @@ -31,8 +31,8 @@ Facebook.requestCredential = (options, credentialRequestCompleteCallback) => { const loginStyle = OAuth._loginStyle('facebook', config, options); let loginUrl = - `https://www.facebook.com/v5.0/dialog/oauth?client_id=${config.appId}` + - `&redirect_uri=${OAuth._redirectUri('facebook', config)}` + + `https://www.facebook.com/v8.0/dialog/oauth?client_id=${config.appId}` + + `&redirect_uri=${OAuth._redirectUri('facebook', config, options.params, options.absoluteUrlOptions)}` + `&display=${display}&scope=${scope}` + `&state=${OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl)}`; diff --git a/packages/facebook-oauth/facebook_server.js b/packages/facebook-oauth/facebook_server.js index f761bf52b4..08331bbb6a 100644 --- a/packages/facebook-oauth/facebook_server.js +++ b/packages/facebook-oauth/facebook_server.js @@ -16,7 +16,7 @@ Facebook.handleAuthFromAccessToken = (accessToken, expiresAt) => { expiresAt, ...fields, }; - + return { serviceData, options: {profile: {name: identity.name}} @@ -31,15 +31,24 @@ OAuth.registerService('facebook', 2, null, query => { return Facebook.handleAuthFromAccessToken(accessToken, (+new Date) + (1000 * expiresIn)); }); -// checks whether a string parses as JSON -const isJSON = str => { - try { - JSON.parse(str); - return true; - } catch (e) { - return false; +function getAbsoluteUrlOptions(query) { + const overrideRootUrlFromStateRedirectUrl = Meteor.settings?.packages?.['facebook-oauth']?.overrideRootUrlFromStateRedirectUrl; + if (!overrideRootUrlFromStateRedirectUrl) { + return undefined; } -}; + try { + const state = OAuth._stateFromQuery(query) || {}; + const redirectUrl = new URL(state.redirectUrl); + return { + rootUrl: redirectUrl.origin, + } + } catch (e) { + console.error( + `Failed to complete OAuth handshake with Facebook because it was not able to obtain the redirect url from the state and you are using overrideRootUrlFromStateRedirectUrl.`, e + ); + return undefined; + } +} // returns an object containing: // - accessToken @@ -51,12 +60,15 @@ const getTokenResponse = query => { let responseContent; try { + + const absoluteUrlOptions = getAbsoluteUrlOptions(query); + const redirectUri = OAuth._redirectUri('facebook', config, undefined, absoluteUrlOptions); // Request an access token responseContent = HTTP.get( - "https://graph.facebook.com/v5.0/oauth/access_token", { + "https://graph.facebook.com/v8.0/oauth/access_token", { params: { client_id: config.appId, - redirect_uri: OAuth._redirectUri('facebook', config), + redirect_uri: redirectUri, client_secret: OAuth.openSecret(config.secret), code: query.code } @@ -92,7 +104,7 @@ const getIdentity = (accessToken, fields) => { hmac.update(accessToken); try { - return HTTP.get("https://graph.facebook.com/v5.0/me", { + return HTTP.get("https://graph.facebook.com/v8.0/me", { params: { access_token: accessToken, appsecret_proof: hmac.digest('hex'), diff --git a/packages/facebook-oauth/package.js b/packages/facebook-oauth/package.js index 0ed950e060..b789d4fd98 100644 --- a/packages/facebook-oauth/package.js +++ b/packages/facebook-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Facebook OAuth flow", - version: "1.7.0" + version: "1.7.4" }); Package.onUse(api => { diff --git a/packages/hot-module-replacement/README.md b/packages/hot-module-replacement/README.md new file mode 100644 index 0000000000..e11e9a8c59 --- /dev/null +++ b/packages/hot-module-replacement/README.md @@ -0,0 +1,3 @@ +# hot-module-replacement + +Adds Hot Module Replacement. diff --git a/packages/hot-module-replacement/client.js b/packages/hot-module-replacement/client.js new file mode 100644 index 0000000000..393a3bf00e --- /dev/null +++ b/packages/hot-module-replacement/client.js @@ -0,0 +1,476 @@ +// TODO: add an api to Reify to update cached exports for a module +const ReifyEntry = require('/node_modules/meteor/modules/node_modules/reify/lib/runtime/entry.js') + +const SOURCE_URL_PREFIX = "meteor://\u{1f4bb}app"; + +// Due to the bundler and proxy running in the same node process +// this could possibly be ran after the next build finished +// TODO: the builder should inject a build timestamp in the bundle +let lastUpdated = Date.now(); +let appliedChangeSets = []; +let removeErrorMessage = null; + +let arch = __meteor_runtime_config__.isModern ? 'web.browser' : 'web.browser.legacy'; +let enabled = arch === 'web.browser'; + +if (!enabled) { + console.log(`HMR is not supported in ${arch}`); +} + + +const imported = Object.create(null); +const importedBy = Object.create(null); + +if (module._onRequire) { + module._onRequire({ + before(importedModule, parentId) { + if (parentId === module.id) { + // While applying updates we import modules to re-run them. + // Don't track those imports since we don't want them to affect + // if a future change to the file can be accepted + return; + } + imported[parentId] = imported[parentId] || new Set(); + imported[parentId].add(importedModule.id); + + importedBy[importedModule.id] = importedBy[importedModule.id] || new Set(); + importedBy[importedModule.id].add(parentId); + }, + }); +} + +let pendingReload = () => Reload._reload({ immediateMigration: true }); +let mustReload = false; + +function handleMessage(message) { + if (message.type === 'register-failed') { + if (message.reason === 'wrong-app') { + console.log('HMR: A different app is running on', Meteor.absoluteUrl()); + console.log('HMR: Once you start this app again reload the page to re-enable HMR'); + } else if (message.reason === 'wrong-secret') { + // TODO: we could wait until the first update to use hot code push + // instead of reloading the page immediately in case the user has any + // client state they want to keep for now. + console.log('HMR: Have the wrong secret, possibly because Meteor was restarted'); + console.log('HMR: Reloading page to get new secret'); + mustReload = true; + pendingReload(); + } else { + console.log(`HMR: Register failed for unknown reason`, message); + } + return; + } else if (message.type === 'app-state') { + if (removeErrorMessage) { + removeErrorMessage(); + } + + if (message.state === 'error' && Package['dev-error-overlay']) { + removeErrorMessage = Package['dev-error-overlay'] + .DevErrorOverlay + .showMessage('Your app is crashing. Here are the latest logs:', message.log.join('\n')); + } + + return; + } + + if (message.type !== 'changes') { + throw new Error(`Unknown HMR message type ${message.type}`); + } + + const hasUnreloadable = message.changeSets.find(changeSet => { + return !changeSet.reloadable; + }); + + if ( + pendingReload && + hasUnreloadable || + message.changeSets.length === 0 + ) { + if (message.eager) { + // This was an attempt to reload before the build finishes + // If we can't, we will wait until the build finishes to properly handle it + return; + } + + console.log('HMR: Unable to do HMR. Falling back to hot code push.') + // Complete hot code push if we can not do hot module reload + mustReload = true; + return pendingReload(); + } + + // In case the user changed how a module works with HMR + // in one of the earlier change sets, we want to apply each + // change set one at a time in order. + const succeeded = message.changeSets.filter(changeSet => { + return !appliedChangeSets.includes(changeSet.id) + }).every(changeSet => { + const applied = applyChangeset(changeSet, message.eager); + + // We don't record if a module is unreplaceable + // during an eager update so we can retry and + // handle the failure after the build finishes + if (applied || !message.eager) { + appliedChangeSets.push(changeSet.id); + } + + return applied; + }); + + if (message.eager) { + // We will ignore any failures at this time + // and wait to handle them until the build finishes + return; + } + + if (!succeeded) { + if (pendingReload) { + console.log('HMR: Some changes can not be applied with HMR. Using hot code push.') + mustReload = true; + return pendingReload(); + } + + throw new Error('HMR failed and unable to fallback to hot code push?'); + } + + if (message.changeSets.length > 0) { + lastUpdated = message.changeSets[message.changeSets.length - 1].linkedAt; + } +} + +let socket; +let pendingMessages = []; + +function send(message) { + if (socket) { + socket.send(JSON.stringify(message)); + } else { + pendingMessages.push(message); + } +} + +function connect() { + if (mustReload) { + // The page will reload, no reason to + // connect and show more logs in the console + return; + } + + let wsUrl = Meteor.absoluteUrl('/__meteor__hmr__/websocket'); + const protocol = wsUrl.startsWith('https://') ? 'wss://' : 'ws://'; + wsUrl = wsUrl.replace(/^.+\/\//, protocol); + socket = new WebSocket(wsUrl); + + socket.addEventListener('close', function () { + socket = null; + console.log('HMR: websocket closed'); + setTimeout(connect, 2000); + }); + + socket.addEventListener('open', function () { + console.log('HMR: connected'); + socket.send(JSON.stringify({ + type: 'register', + arch, + secret: __meteor_runtime_config__._hmrSecret, + appId: __meteor_runtime_config__.appId, + })); + + const toSend = pendingMessages.slice(); + pendingMessages = []; + + toSend.forEach(message => { + send(message); + }); + }); + + socket.addEventListener('message', function (event) { + handleMessage(JSON.parse(event.data)); + }); + + socket.addEventListener('error', console.error); +} + +connect(); + +function requestChanges() { + send({ + type: 'request-changes', + arch, + after: lastUpdated + }); +} + +function walkTree(pathParts, tree) { + const part = pathParts.shift(); + const _module = tree.contents[part]; + + if (!_module) { + console.log('HMR: file does not exist', part, pathParts, _module, tree); + throw new Error('not-exist'); + } + + if (pathParts.length === 0) { + return _module; + } + + return walkTree(pathParts, _module); +} + +function findFile(moduleId) { + return walkTree(moduleId.split('/').slice(1), module._getRoot()); +} + +// btoa with unicode support +function utoa(data) { + return btoa(unescape(encodeURIComponent(data))); +} + +function createInlineSourceMap(map) { + return "//# sourceMappingURL=data:application/json;base64," + utoa(JSON.stringify(map)); +} + +function createModuleContent (code, map) { + return function () { + return eval( + // Wrap the function(require,exports,module){...} expression in + // parentheses to force it to be parsed as an expression. + // The sourceURL is treated as a prefix for the sources array + // in the source map + "(" + code + ")\n//# sourceURL=" + SOURCE_URL_PREFIX + + "\n" + createInlineSourceMap(map) + ).apply(this, arguments); + } +} + +function replaceFileContent(file, contents) { + // TODO: to replace content in packages, we need an eval function that runs + // within the package scope, like dynamic imports does. + const moduleFunction = createModuleContent(contents.code, contents.map, file.module.id); + + file.contents = moduleFunction; +} + +function checkModuleAcceptsUpdate(moduleId, checked) { + checked.add(moduleId); + + if (moduleId === '/' ) { + return false; + } + + const file = findFile(moduleId); + const moduleHot = file.module.hot; + const moduleAccepts = moduleHot ? moduleHot._canAcceptUpdate() : false; + + if (moduleAccepts !== null) { + return moduleAccepts; + } + + let accepts = null; + + // The module did not accept the update. If the update is accepted depends + // on if the modules that imported this module accept the update. + importedBy[moduleId].forEach(depId => { + if (depId === '/' && importedBy[moduleId].size > 1) { + // This module was eagerly required by Meteor. + // Meteor won't know if the module can be updated + // but we can check with the other modules that imported it. + return; + } + + if (checked.has(depId)) { + // There is a circular dependency + return; + } + + const depResult = checkModuleAcceptsUpdate(depId, checked); + + if (accepts !== false) { + accepts = depResult; + } + }); + + return accepts === null ? false : accepts; +} + +function addFiles(addedFiles) { + addedFiles.forEach(file => { + const tree = {}; + const segments = file.path.split('/').slice(1); + const fileName = segments.pop(); + + let previous = tree; + segments.forEach(segment => { + previous[segment] = previous[segment] || {} + previous = previous[segment] + }); + previous[fileName] = createModuleContent( + file.content.code, + file.content.map, + file.path + ); + + meteorInstall(tree, file.meteorInstallOptions); + }); +} + +module.constructor.prototype._reset = function (id) { + const moduleId = id || this.id; + const file = findFile(moduleId); + + const hotState = file.module._hotState; + + const hotData = {}; + hotState._disposeHandlers.forEach(cb => { + cb(hotData); + }); + + hotState.data = hotData; + hotState._disposeHandlers = []; + hotState._hotAccepts = null; + + + // Clear cached exports + // TODO: check how this affects live bindings for ecmascript modules + delete file.module.exports; + const entry = ReifyEntry.getOrCreate(moduleId); + entry.getters = {}; + entry.setters = {}; + entry.module = null; + Object.keys(entry.namespace).forEach(key => { + if (key !== '__esModule') { + delete entry.namespace[key]; + } + }); + + if (imported[moduleId]) { + imported[moduleId].forEach(depId => { + importedBy[depId].delete(moduleId); + }); + imported[moduleId] = new Set(); + } +} + +module.constructor.prototype._replaceModule = function (id, contents) { + const moduleId = id || this.id; + const root = this._getRoot(); + + let file; + try { + file = walkTree(moduleId.split('/').slice(1), root); + } catch (e) { + if (e.message === 'not-exist') { + return null; + } + + throw e; + } + + if (!file.contents) { + // File is a dynamic import that hasn't been loaded + return; + } + + replaceFileContent(file, contents); + + if (!file.module.exports) { + // File hasn't been imported. + return; + } +} + +function applyChangeset({ + changedFiles, + addedFiles +}) { + let canApply = true; + let toRerun = new Set(); + + changedFiles.forEach(({ path }) => { + const file = findFile(path); + + // Check if the file has been imported. If it hasn't been, + // we can assume update to it can be accepted + if (file.module.exports) { + const checked = new Set(); + const accepts = checkModuleAcceptsUpdate(path, checked); + + if (canApply) { + canApply = accepts; + checked.forEach(moduleId => { + toRerun.add(moduleId); + }); + } + } + }); + + if (!canApply) { + return false; + } + + + changedFiles.forEach(({ content, path }) => { + module._replaceModule(path, content); + }); + + if (addedFiles.length > 0) { + addFiles(addedFiles); + } + + toRerun.forEach(moduleId => { + const file = findFile(moduleId); + // clear module caches and hot state + file.module._reset(); + file.module.loaded = false; + }); + + try { + toRerun.forEach(moduleId => { + require(moduleId); + }); + } catch (error) { + console.error('HMR: Error while applying changes:', error); + } + + const updateCount = changedFiles.length + addedFiles.length; + console.log(`HMR: updated ${updateCount} ${updateCount === 1 ? 'file' : 'files'}`); + return true; +} + +const initialVersions = (__meteor_runtime_config__.autoupdate.versions || {})['web.browser']; +let nonRefreshableVersion = initialVersions.versionNonRefreshable; +let replaceableVersion = initialVersions.versionReplaceable; + +Meteor.startup(() => { + if (!enabled) { + return; + } + + Package['autoupdate'].Autoupdate._clientVersions.watch((doc) => { + if (doc._id !== 'web.browser') { + return; + } + + if (nonRefreshableVersion !== doc.versionNonRefreshable) { + nonRefreshableVersion = doc.versionNonRefreshable; + console.log('HMR: Some changes can not be applied with HMR. Using hot code push.') + mustReload = true; + pendingReload(); + } else if (doc.versionReplaceable !== replaceableVersion) { + replaceableVersion = doc.versionReplaceable; + requestChanges(); + } + }); + + // We disable hot code push for js until there were + // changes that can not be applied through HMR. + Package['reload'].Reload._onMigrate((tryReload) => { + if (mustReload) { + return [true]; + } + + pendingReload = tryReload; + requestChanges(); + + return [false]; + }); +}); diff --git a/packages/hot-module-replacement/hot-api.js b/packages/hot-module-replacement/hot-api.js new file mode 100644 index 0000000000..ab2679f629 --- /dev/null +++ b/packages/hot-module-replacement/hot-api.js @@ -0,0 +1,92 @@ +const meteorInstall = Package['modules-runtime'].meteorInstall; + +/** + * @summary The Hot API used to configure HMR + * @memberof module + * @name hot + */ +Object.defineProperty(meteorInstall.Module.prototype, "hot", { + get: function () { + if (!this._hotState) { + this._hotState = { + // if null, whether it accepts depends on all of the modules that + // required it + _hotAccepts: null, + _disposeHandlers: [], + data: null + }; + } + + let hotState = this._hotState; + let module = this; + + return { + /** + * @summary Accept updates to this module. Also applies to its dependencies, + * as long as the other modules that import the dependencies also accept + * updates. + * @locus Client + * @memberOf module.hot + * @instance + * @name accept + */ + accept() { + if (arguments.length > 0) { + console.warn('hot.accept does not support any arguments.'); + } + hotState._hotAccepts = true; + }, + /** + * @summary Disable updating this module or its dependencies with HMR. + * Hot code push will be used instead. + * @locus Client + * @memberOf module.hot + * @instance + * @name decline + */ + decline() { + if (arguments.length > 0) { + throw new Error('hot.decline does not support any arguments.'); + } + + hotState._hotAccepts = false; + }, + /** + * @summary Add a call back to clean up the module before replacing it + * @locus Client + * @memberOf module.hot + * @instance + * @name dispose + * @param {module.hot.DisposeFunction} callback Called before replacing the old module. + */ + dispose(cb) { + hotState._disposeHandlers.push(cb); + }, + /** + * @summary Add callbacks to run before and after a module is required + * @locus Client + * @memberOf module.hot + * @instance + * @name onRequire + * @param {Object} callbacks Can have before and after methods, called before a module is required, + * and after it finished being evaluated + */ + onRequire(callbacks) { + return module._onRequire(callbacks); + }, + _canAcceptUpdate() { + return hotState._hotAccepts; + }, + /** + * @summary Defaults to null. When the module is replaced, + * this is set to the object passed to dispose handlers. + * @locus Client + * @memberOf module.hot + * @instance + * @name data + */ + data: hotState.data + } + }, + set() { } +}); diff --git a/packages/hot-module-replacement/package.js b/packages/hot-module-replacement/package.js new file mode 100644 index 0000000000..69327361f7 --- /dev/null +++ b/packages/hot-module-replacement/package.js @@ -0,0 +1,22 @@ +Package.describe({ + name: 'hot-module-replacement', + version: '0.2.0', + summary: 'Update code in development without reloading the page', + documentation: 'README.md', + debugOnly: true +}); + +Package.onUse(function (api) { + api.use('modules'); + api.use('meteor'); + api.use('dev-error-overlay', { weak: true }); + api.imply('modules-runtime-hot@0.12.0'); + api.addFiles([ + './hot-api.js', + './client.js' + ], 'client'); + api.addFiles('./server.js', 'server'); +}); + +Package.onTest(function (api) { +}); diff --git a/packages/hot-module-replacement/server.js b/packages/hot-module-replacement/server.js new file mode 100644 index 0000000000..aa08e9a8ef --- /dev/null +++ b/packages/hot-module-replacement/server.js @@ -0,0 +1,5 @@ +if (!process.env.METEOR_HMR_SECRET) { + console.log('Restart Meteor to enable hot module replacement.'); +} else { + __meteor_runtime_config__._hmrSecret = process.env.METEOR_HMR_SECRET; +} diff --git a/packages/logging/.npm/package/npm-shrinkwrap.json b/packages/logging/.npm/package/npm-shrinkwrap.json index 8ac3846592..beceaf26cb 100644 --- a/packages/logging/.npm/package/npm-shrinkwrap.json +++ b/packages/logging/.npm/package/npm-shrinkwrap.json @@ -1,34 +1,87 @@ { "lockfileVersion": 1, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, "cli-color": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.2.3.tgz", - "integrity": "sha1-CiXOrlpqFgK+f3fShWPDZwAnTog=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.0.tgz", + "integrity": "sha512-a0VZ8LeraW0jTuCkuAGMNufareGHhyZU9z8OGsW0gXd1hZGi1SRuNRXdbGkraBBKnhyUhyebFWnRbp+dIn0f0A==" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==" + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==" + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==" + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=" + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", "dependencies": { - "es5-ext": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.9.2.tgz", - "integrity": "sha1-0uMJ0fIjsHGGSINaz1uII6gGH4o=" - }, - "memoizee": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.2.5.tgz", - "integrity": "sha1-RK0M5zQ5cF85VKWNv195LNSWwBw=", - "dependencies": { - "event-emitter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.2.2.tgz", - "integrity": "sha1-yB43JOtVQHxaDV7jKZQR9wD1QpE=" - }, - "next-tick": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.1.0.tgz", - "integrity": "sha1-GRLM6OubaX1kD7upT48A3sO5Qlk=" - } - } + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" } } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=" + }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" } } } diff --git a/packages/logging/logging.js b/packages/logging/logging.js index b352392641..ea2b945e1b 100644 --- a/packages/logging/logging.js +++ b/packages/logging/logging.js @@ -176,8 +176,8 @@ Log._getCallerDetails = () => { obj.time = new Date(); obj.level = level; - // XXX allow you to enable 'debug', probably per-package - if (level === 'debug') { + // If we are in production don't write out debug logs. + if (level === 'debug' && Meteor.isProduction) { return; } diff --git a/packages/logging/logging_cordova.js b/packages/logging/logging_cordova.js index dfa3290394..7ac528befb 100644 --- a/packages/logging/logging_cordova.js +++ b/packages/logging/logging_cordova.js @@ -1,5 +1,5 @@ // Log all uncaught errors so they can be printed to the developer. -// But since Android's adb catlog already prints the uncaught exceptions, we +// But since Android's adb catalog already prints the uncaught exceptions, we // can disable it for Android. if (! /Android/i.test(navigator.userAgent)) { window.onerror = function (msg, url, line) { diff --git a/packages/logging/package.js b/packages/logging/package.js index 65ad237c67..c40f3e7834 100644 --- a/packages/logging/package.js +++ b/packages/logging/package.js @@ -1,27 +1,23 @@ Package.describe({ summary: 'Logging facility.', - version: '1.1.20' + version: '1.2.0' }); Npm.depends({ - 'cli-color': '0.2.3' + 'cli-color': '2.0.0' }); Npm.strip({ 'es5-ext': ['test/'] }); -Cordova.depends({ - 'cordova-plugin-console': '1.1.0' // Deprecated, remove in future -}); - Package.onUse(function (api) { api.export('Log'); // The `ecmascript-runtime-client` package is explicitly depended upon // here due to this package's dependency on // `String.prototype.padRight` which is polyfilled only in // `ecmascript-runtime-client@0.6.2` or newer. - api.use(['ejson', 'ecmascript', 'ecmascript-runtime-client@0.6.2']); + api.use(['ejson', 'ecmascript', 'ecmascript-runtime-client']); api.mainModule('logging.js'); api.mainModule('logging_cordova.js', 'web.cordova'); }); diff --git a/packages/meteor-developer-oauth/meteor_developer_client.js b/packages/meteor-developer-oauth/meteor_developer_client.js index bd5c5688d3..feeaea6af5 100644 --- a/packages/meteor-developer-oauth/meteor_developer_client.js +++ b/packages/meteor-developer-oauth/meteor_developer_client.js @@ -27,7 +27,7 @@ const requestCredential = (options, credentialRequestCompleteCallback) => { "/oauth2/authorize?" + `state=${OAuth._stateParam(loginStyle, credentialToken, options && options.redirectUrl)}` + "&response_type=code&" + - `client_id=${config.clientId}`; + `client_id=${config.clientId}${options && options.details ? `&details=${options && options.details}` : ''}`; /** * @deprecated in 1.3.0 @@ -49,7 +49,7 @@ const requestCredential = (options, credentialRequestCompleteCallback) => { loginUrl, credentialRequestCompleteCallback, credentialToken, - popupOptions: {width: 470, height: 490} + popupOptions: {width: 497, height: 749} }); }; diff --git a/packages/meteor-developer-oauth/package.js b/packages/meteor-developer-oauth/package.js index 02702b8dec..6f63381878 100644 --- a/packages/meteor-developer-oauth/package.js +++ b/packages/meteor-developer-oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Meteor developer accounts OAuth flow', - version: '1.2.1' + version: '1.2.3' }); Package.onUse(api => { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index c00dc12696..490eba935f 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.11.0' + version: '2.1.0' }); Package.includeTool(); diff --git a/packages/meteor/helpers.js b/packages/meteor/helpers.js index 54ebbe3ae7..e64921a5ef 100644 --- a/packages/meteor/helpers.js +++ b/packages/meteor/helpers.js @@ -81,7 +81,12 @@ Meteor._delete = function (obj /*, arguments */) { /** * @memberOf Meteor - * @summary Wrap a function that takes a callback function as its final parameter. The signature of the callback of the wrapped function should be `function(error, result){}`. On the server, the wrapped function can be used either synchronously (without passing a callback) or asynchronously (when a callback is passed). On the client, a callback is always required; errors will be logged if there is no callback. If a callback is provided, the environment captured when the original function was called will be restored in the callback. + * @summary Wrap a function that takes a callback function as its final parameter. + * The signature of the callback of the wrapped function should be `function(error, result){}`. + * On the server, the wrapped function can be used either synchronously (without passing a callback) or asynchronously + * (when a callback is passed). On the client, a callback is always required; errors will be logged if there is no callback. + * If a callback is provided, the environment captured when the original function was called will be restored in the callback. + * The parameters of the wrapped function must not contain any optional parameters or be undefined, as the callback function is expected to be the final, non-undefined parameter. * @locus Anywhere * @param {Function} func A function that takes a callback as its final parameter * @param {Object} [context] Optional `this` object against which the original function will be invoked diff --git a/packages/minifier-css/.gitignore b/packages/minifier-css/.gitignore index 677a6fc263..c01644335c 100644 --- a/packages/minifier-css/.gitignore +++ b/packages/minifier-css/.gitignore @@ -1 +1,2 @@ .build* +.npm diff --git a/packages/minifier-css/.npm/package/npm-shrinkwrap.json b/packages/minifier-css/.npm/package/npm-shrinkwrap.json index 0cf06de439..4fee0a023f 100644 --- a/packages/minifier-css/.npm/package/npm-shrinkwrap.json +++ b/packages/minifier-css/.npm/package/npm-shrinkwrap.json @@ -27,9 +27,9 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "browserslist": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", - "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==" + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", + "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==" }, "caller-callsite": { "version": "2.0.0", @@ -52,9 +52,9 @@ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" }, "caniuse-lite": { - "version": "1.0.30001066", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001066.tgz", - "integrity": "sha512-Gfj/WAastBtfxLws0RCh2sDbTK/8rJuSeZMecrSkNGYxPcv7EzblmDGfWQCFEQcSqYE2BRgQiJh8HOD07N5hIw==" + "version": "1.0.30001125", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001125.tgz", + "integrity": "sha512-9f+r7BW8Qli917mU3j0fUaTweT3f3vnX/Lcs+1C73V+RADmFme+Ih0Br8vONQi3X0lseOe6ZHfsZLCA8MSjxUA==" }, "chalk": { "version": "2.4.2", @@ -124,9 +124,9 @@ "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==" }, "css-what": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", - "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==" }, "cssesc": { "version": "3.0.0", @@ -208,19 +208,19 @@ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" }, "dot-prop": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", - "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" }, "electron-to-chromium": { - "version": "1.3.453", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.453.tgz", - "integrity": "sha512-IQbCfjJR0NDDn/+vojTlq7fPSREcALtF8M1n01gw7nQghCtfFYrJ2dfhsp8APr8bANoFC8vRTFVXMOGpT0eetw==" + "version": "1.3.564", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz", + "integrity": "sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==" }, "entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz", - "integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, "error-ex": { "version": "1.3.2", @@ -228,15 +228,20 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==" + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==" }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==" }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -247,11 +252,6 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -313,9 +313,9 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", + "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==" }, "is-color-stop": { "version": "1.1.0", @@ -338,9 +338,9 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==" }, "is-resolvable": { "version": "1.1.0", @@ -367,11 +367,6 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -398,9 +393,9 @@ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" }, "node-releases": { - "version": "1.1.57", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.57.tgz", - "integrity": "sha512-ZQmnWS7adi61A9JsllJ2gdj2PauElcjnOwTp2O011iGzoakTxUsDGSe+6vD7wXbKdqhSFymC0OSx35aAMhrSdw==" + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==" }, "normalize-url": { "version": "3.3.0", @@ -413,9 +408,9 @@ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==" }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" }, "object-keys": { "version": "1.1.1", @@ -437,45 +432,20 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==" }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=" }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=" - }, "postcss": { - "version": "7.0.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.31.tgz", - "integrity": "sha512-a937VDHE1ftkjk+8/7nj/mrjtmkn69xxzJgRETXdAUU+IgOYPQNJF17haGWbeDxSyk++HA14UA98FurvPyBJOA==" + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==" }, "postcss-calc": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", - "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==" + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.4.tgz", + "integrity": "sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw==" }, "postcss-colormin": { "version": "4.0.3", @@ -807,16 +777,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==" }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==" - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==" - }, "string.prototype.trimstart": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", diff --git a/packages/minifier-css/package.js b/packages/minifier-css/package.js index 3cf0016536..eec87a69bc 100644 --- a/packages/minifier-css/package.js +++ b/packages/minifier-css/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: 'CSS minifier', - version: '1.5.2' + version: '1.5.3' }); Npm.depends({ - postcss: '7.0.31', + postcss: '7.0.32', cssnano: '4.1.10' }); diff --git a/packages/minimongo/local_collection.js b/packages/minimongo/local_collection.js index e767137089..38b4d5c3a6 100644 --- a/packages/minimongo/local_collection.js +++ b/packages/minimongo/local_collection.js @@ -880,7 +880,7 @@ LocalCollection._compileProjection = fields => { const result = details.including ? {} : EJSON.clone(doc); Object.keys(ruleTree).forEach(key => { - if (!hasOwn.call(doc, key)) { + if (doc == null || !hasOwn.call(doc, key)) { return; } @@ -899,7 +899,7 @@ LocalCollection._compileProjection = fields => { } }); - return result; + return doc != null ? result : doc; }; return doc => { diff --git a/packages/minimongo/minimongo_tests_client.js b/packages/minimongo/minimongo_tests_client.js index 24455b439e..658f8e12db 100644 --- a/packages/minimongo/minimongo_tests_client.js +++ b/packages/minimongo/minimongo_tests_client.js @@ -1781,13 +1781,13 @@ Tinytest.add('minimongo - fetch with projection, subarrays', test => { fieldB: 'the bad', fieldC: 'the ugly', }], - setB: [{ + setB: [null, { anotherA: { }, anotherB: 'meh', - }, { + }, null, { anotherA: 1234, anotherB: 431, - }], + }, null], }); const equalNonStrict = (a, b, desc) => { @@ -1802,13 +1802,13 @@ Tinytest.add('minimongo - fetch with projection, subarrays', test => { testForProjection({ 'setA.fieldA': 1, 'setB.anotherB': 1, _id: 0 }, { setA: [{ fieldA: 42 }, { fieldA: 'the good' }], - setB: [{ anotherB: 'meh' }, { anotherB: 431 }], + setB: [null, { anotherB: 'meh' }, null, { anotherB: 431 }, null], }); testForProjection({ 'setA.fieldA': 0, 'setB.anotherA': 0, _id: 0 }, { setA: [{fieldB: 33}, {fieldB: 'the bad', fieldC: 'the ugly'}], - setB: [{ anotherB: 'meh' }, { anotherB: 431 }], + setB: [null, { anotherB: 'meh' }, null, { anotherB: 431 }, null], }); c.remove({}); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index ef6627f5a1..826e59b3b4 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.6.0' + version: '1.6.1' }); Package.onUse(api => { diff --git a/packages/modules-runtime-hot/README.md b/packages/modules-runtime-hot/README.md new file mode 100644 index 0000000000..b73156b591 --- /dev/null +++ b/packages/modules-runtime-hot/README.md @@ -0,0 +1,3 @@ +# modules-runtime-hot + +Patches modules-runtime to support HMR. diff --git a/packages/modules-runtime-hot/installer.js b/packages/modules-runtime-hot/installer.js new file mode 100644 index 0000000000..ed346c2739 --- /dev/null +++ b/packages/modules-runtime-hot/installer.js @@ -0,0 +1,598 @@ +makeInstaller = function (options) { + "use strict"; + + options = options || {}; + + // These file extensions will be appended to required module identifiers + // if they do not exactly match an installed module. + var defaultExtensions = options.extensions || [".js", ".json"]; + + // If defined, the options.fallback function will be called when no + // installed module is found for a required module identifier. Often + // options.fallback will be implemented in terms of the native Node + // require function, which has the ability to load binary modules. + var fallback = options.fallback; + + // List of fields to look for in package.json files to determine the + // main entry module of the package. The first field listed here whose + // value is a string will be used to resolve the entry module. + var mainFields = options.mainFields || + // If options.mainFields is absent and options.browser is truthy, + // package resolution will prefer the "browser" field of package.json + // files to the "main" field. Note that this only supports + // string-valued "browser" fields for now, though in the future it + // might make sense to support the object version, a la browserify. + (options.browser ? ["browser", "main"] : ["main"]); + + var hasOwn = {}.hasOwnProperty; + function strictHasOwn(obj, key) { + return isObject(obj) && isString(key) && hasOwn.call(obj, key); + } + + // Cache for looking up File objects given absolute module identifiers. + // Invariants: + // filesByModuleId[module.id] === fileAppendId(root, module.id) + // filesByModuleId[module.id].module === module + var filesByModuleId = {}; + + // The file object representing the root directory of the installed + // module tree. + var root = new File("/", new File("/..")); + var rootRequire = makeRequire(root); + + // Merges the given tree of directories and module factory functions + // into the tree of installed modules and returns a require function + // that behaves as if called from a module in the root directory. + function install(tree, options) { + if (isObject(tree)) { + fileMergeContents(root, tree, options); + } + return rootRequire; + } + + // Replace this function to enable Module.prototype.prefetch. + install.fetch = function (ids) { + throw new Error("fetch not implemented"); + }; + + // This constructor will be used to instantiate the module objects + // passed to module factory functions (i.e. the third argument after + // require and exports), and is exposed as install.Module in case the + // caller of makeInstaller wishes to modify Module.prototype. + function Module(id) { + this.id = id; + + // The Node implementation of module.children unfortunately includes + // only those child modules that were imported for the first time by + // this parent module (i.e., child.parent === this). + this.children = []; + + // This object is an install.js extension that includes all child + // modules imported by this module, even if this module is not the + // first to import them. + this.childrenById = {}; + } + + var requireHooks = []; + + // Used to keep module.prefetch promise resolutions well-ordered. + var lastPrefetchPromise; + + // May be shared by multiple sequential calls to module.prefetch. + // Initialized to {} only when necessary. + var missing; + + Module.prototype.prefetch = function (id) { + var module = this; + var parentFile = getOwn(filesByModuleId, module.id); + + lastPrefetchPromise = lastPrefetchPromise || Promise.resolve(); + var previousPromise = lastPrefetchPromise; + + function walk(module) { + var file = getOwn(filesByModuleId, module.id); + if (fileIsDynamic(file) && !file.pending) { + file.pending = true; + missing = missing || {}; + + // These are the data that will be exposed to the install.fetch + // callback, so it's worth documenting each item with a comment. + missing[module.id] = { + // The CommonJS module object that will be exposed to this + // dynamic module when it is evaluated. Note that install.fetch + // could decide to populate module.exports directly, instead of + // fetching anything. In that case, install.fetch should omit + // this module from the tree that it produces. + module: file.module, + // List of module identifier strings imported by this module. + // Note that the missing object already contains all available + // dependencies (including transitive dependencies), so + // install.fetch should not need to traverse these dependencies + // in most cases; however, they may be useful for other reasons. + // Though the strings are unique, note that two different + // strings could resolve to the same module. + deps: Object.keys(file.deps), + // The options (if any) that were passed as the second argument + // to the install(tree, options) function when this stub was + // first registered. Typically contains options.extensions, but + // could contain any information appropriate for the entire tree + // as originally installed. These options will be automatically + // inherited by the newly fetched modules, so install.fetch + // should not need to modify them. + options: file.options, + // Any stub data included in the array notation from the + // original entry for this dynamic module. Typically contains + // "main" and/or "browser" fields for package.json files, and is + // otherwise undefined. + stub: file.stub + }; + + each(file.deps, function (parentId, id) { + fileResolve(file, id); + }); + + each(module.childrenById, walk); + } + } + + return lastPrefetchPromise = new Promise(function (resolve) { + var absChildId = module.resolve(id); + each(module.childrenById, walk); + resolve(absChildId); + + }).then(function (absChildId) { + // Grab the current missing object and fetch its contents. + var toBeFetched = missing; + missing = null; + + function clearPending() { + if (toBeFetched) { + Object.keys(toBeFetched).forEach(function (id) { + getOwn(filesByModuleId, id).pending = false; + }); + } + } + + return new Promise(function (resolve) { + // The install.fetch function takes an object mapping missing + // dynamic module identifiers to options objects, and should + // return a Promise that resolves to a module tree that can be + // installed. As an optimization, if there were no missing dynamic + // modules, then we can skip calling install.fetch entirely. + resolve(toBeFetched && install.fetch(toBeFetched)); + + }).then(function (tree) { + function both() { + install(tree); + clearPending(); + return absChildId; + } + + // Although we want multiple install.fetch calls to run in + // parallel, it is important that the promises returned by + // module.prefetch are resolved in the same order as the original + // calls to module.prefetch, because previous fetches may include + // modules assumed to exist by more recent module.prefetch calls. + // Whether previousPromise was resolved or rejected, carry on with + // the installation regardless. + return previousPromise.then(both, both); + + }, function (error) { + // Fixes https://github.com/meteor/meteor/issues/10182. + clearPending(); + throw error; + }); + }); + }; + + install.Module = Module; + + function getOwn(obj, key) { + return strictHasOwn(obj, key) && obj[key]; + } + + function isObject(value) { + return value !== null && typeof value === "object"; + } + + function isFunction(value) { + return typeof value === "function"; + } + + function isString(value) { + return typeof value === "string"; + } + + function makeMissingError(id) { + return new Error("Cannot find module '" + id + "'"); + } + + Module.prototype.onRequire = function (callbacks) { + console.warn('module.onRequire is depreciated. Use module.hot.onRequire instead.'); + this._onRequire(callbacks); + }; + + Module.prototype._onRequire = function (callbacks) { + requireHooks.push(callbacks); + }; + + Module.prototype.resolve = function (id) { + var file = fileResolve(filesByModuleId[this.id], id); + if (file) return file.module.id; + var error = makeMissingError(id); + if (fallback && isFunction(fallback.resolve)) { + return fallback.resolve(id, this.id, error); + } + throw error; + }; + + Module.prototype.require = function require(id) { + var result = fileResolve(filesByModuleId[this.id], id); + + if (result) { + // Skip any hooks added while requiring this module + var hookCount = requireHooks.length; + var hookData = [] + + for (var i = 0; i < hookCount; i++) { + if (requireHooks[i].before) { + hookData.push(requireHooks[i].before(result.module, this.id)); + } + } + + var moduleExports = fileEvaluate(result, this); + + for (var i = 0; i < hookCount; i++) { + if (requireHooks[i].after) { + requireHooks[i].after(result.module, hookData[i]); + } + } + + return moduleExports; + } + + var error = makeMissingError(id); + + if (isFunction(fallback)) { + return fallback( + id, // The missing module identifier. + this.id, // ID of the parent module. + error // The error we would have thrown. + ); + } + + throw error; + }; + + Module.prototype._getRoot = function () { + return root; + } + + Module.prototype._getModuleById = function (id) { + var result = fileResolve(filesByModuleId[this.id], id); + if (result) { + return result.module; + } + return null; + } + + function makeRequire(file) { + var module = file.module; + + function require(id) { + return module.require(id); + } + + require.extensions = fileGetExtensions(file).slice(0); + + require.resolve = function resolve(id) { + return module.resolve(id); + }; + + return require; + } + + // File objects represent either directories or modules that have been + // installed. When a `File` respresents a directory, its `.contents` + // property is an object containing the names of the files (or + // directories) that it contains. When a `File` represents a module, its + // `.contents` property is a function that can be invoked with the + // appropriate `(require, exports, module)` arguments to evaluate the + // module. If the `.contents` property is a string, that string will be + // resolved as a module identifier, and the exports of the resulting + // module will provide the exports of the original file. The `.parent` + // property of a File is either a directory `File` or `null`. Note that + // a child may claim another `File` as its parent even if the parent + // does not have an entry for that child in its `.contents` object. + // This is important for implementing anonymous files, and preventing + // child modules from using `../relative/identifier` syntax to examine + // unrelated modules. + function File(moduleId, parent) { + var file = this; + + // Link to the parent file. + file.parent = parent = parent || null; + + // The module object for this File, which will eventually boast an + // .exports property when/if the file is evaluated. + file.module = new Module(moduleId); + filesByModuleId[moduleId] = file; + + // The .contents of the file can be either (1) an object, if the file + // represents a directory containing other files; (2) a factory + // function, if the file represents a module that can be imported; (3) + // a string, if the file is an alias for another file; or (4) null, if + // the file's contents are not (yet) available. + file.contents = null; + + // Set of module identifiers imported by this module. Note that this + // set is not necessarily complete, so don't rely on it unless you + // know what you're doing. + file.deps = {}; + } + + function fileEvaluate(file, parentModule) { + var module = file.module; + if (!strictHasOwn(module, "exports")) { + var contents = file.contents; + if (!contents) { + // If this file was installed with array notation, and the array + // contained one or more objects but no functions, then the combined + // properties of the objects are treated as a temporary stub for + // file.module.exports. This is particularly important for partial + // package.json modules, so that the resolution logic can know the + // value of the "main" and/or "browser" fields, at least, even if + // the rest of the package.json file is not (yet) available. + if (file.stub) { + return file.stub; + } + + throw makeMissingError(module.id); + } + + if (parentModule) { + module.parent = parentModule; + var children = parentModule.children; + if (Array.isArray(children)) { + children.push(module); + } + } + + contents( + makeRequire(file), + // If the file had a .stub, reuse the same object for exports. + module.exports = file.stub || {}, + module, + file.module.id, + file.parent.module.id + ); + + module.loaded = true; + } + + // The module.runModuleSetters method will be deprecated in favor of + // just module.runSetters: https://github.com/benjamn/reify/pull/160 + var runSetters = module.runSetters || module.runModuleSetters; + if (isFunction(runSetters)) { + runSetters.call(module); + } + + return module.exports; + } + + function fileIsDirectory(file) { + return file && isObject(file.contents); + } + + function fileIsDynamic(file) { + return file && file.contents === null; + } + + function fileMergeContents(file, contents, options) { + if (Array.isArray(contents)) { + contents.forEach(function (item) { + if (isString(item)) { + file.deps[item] = file.module.id; + } else if (isFunction(item)) { + contents = item; + } else if (isObject(item)) { + file.stub = file.stub || {}; + each(item, function (value, key) { + file.stub[key] = value; + }); + } + }); + + if (!isFunction(contents)) { + // If the array did not contain a function, merge nothing. + contents = null; + } + + } else if (!isFunction(contents) && + !isString(contents) && + !isObject(contents)) { + // If contents is neither an array nor a function nor a string nor + // an object, just give up and merge nothing. + contents = null; + } + + if (contents) { + file.contents = file.contents || (isObject(contents) ? {} : contents); + if (isObject(contents) && fileIsDirectory(file)) { + each(contents, function (value, key) { + if (key === "..") { + child = file.parent; + + } else { + var child = getOwn(file.contents, key); + + if (!child) { + child = file.contents[key] = new File( + file.module.id.replace(/\/*$/, "/") + key, + file + ); + + child.options = options; + } + } + + fileMergeContents(child, value, options); + }); + } + } + } + + function each(obj, callback, context) { + Object.keys(obj).forEach(function (key) { + callback.call(this, obj[key], key); + }, context); + } + + function fileGetExtensions(file) { + return file.options + && file.options.extensions + || defaultExtensions; + } + + function fileAppendIdPart(file, part, extensions) { + // Always append relative to a directory. + while (file && !fileIsDirectory(file)) { + file = file.parent; + } + + if (!file || !part || part === ".") { + return file; + } + + if (part === "..") { + return file.parent; + } + + var exactChild = getOwn(file.contents, part); + + // Only consider multiple file extensions if this part is the last + // part of a module identifier and not equal to `.` or `..`, and there + // was no exact match or the exact match was a directory. + if (extensions && (!exactChild || fileIsDirectory(exactChild))) { + for (var e = 0; e < extensions.length; ++e) { + var child = getOwn(file.contents, part + extensions[e]); + if (child && !fileIsDirectory(child)) { + return child; + } + } + } + + return exactChild; + } + + function fileAppendId(file, id, extensions) { + var parts = id.split("/"); + + // Use `Array.prototype.every` to terminate iteration early if + // `fileAppendIdPart` returns a falsy value. + parts.every(function (part, i) { + return file = i < parts.length - 1 + ? fileAppendIdPart(file, part) + : fileAppendIdPart(file, part, extensions); + }); + + return file; + } + + function recordChild(parentModule, childFile) { + var childModule = childFile && childFile.module; + if (parentModule && childModule) { + parentModule.childrenById[childModule.id] = childModule; + } + } + + function fileResolve(file, id, parentModule, seenDirFiles) { + var parentModule = parentModule || file.module; + var extensions = fileGetExtensions(file); + + file = + // Absolute module identifiers (i.e. those that begin with a `/` + // character) are interpreted relative to the root directory, which + // is a slight deviation from Node, which has access to the entire + // file system. + id.charAt(0) === "/" ? fileAppendId(root, id, extensions) : + // Relative module identifiers are interpreted relative to the + // current file, naturally. + id.charAt(0) === "." ? fileAppendId(file, id, extensions) : + // Top-level module identifiers are interpreted as referring to + // packages in `node_modules` directories. + nodeModulesLookup(file, id, extensions); + + // If the identifier resolves to a directory, we use the same logic as + // Node to find an `index.js` or `package.json` file to evaluate. + while (fileIsDirectory(file)) { + seenDirFiles = seenDirFiles || []; + + // If the "main" field of a `package.json` file resolves to a + // directory we've already considered, then we should not attempt to + // read the same `package.json` file again. Using an array as a set + // is acceptable here because the number of directories to consider + // is rarely greater than 1 or 2. Also, using indexOf allows us to + // store File objects instead of strings. + if (seenDirFiles.indexOf(file) < 0) { + seenDirFiles.push(file); + + var pkgJsonFile = fileAppendIdPart(file, "package.json"); + var pkg = pkgJsonFile && fileEvaluate(pkgJsonFile, parentModule); + var mainFile, resolved = pkg && mainFields.some(function (name) { + var main = pkg[name]; + if (isString(main)) { + // The "main" field of package.json does not have to begin + // with ./ to be considered relative, so first we try + // simply appending it to the directory path before + // falling back to a full fileResolve, which might return + // a package from a node_modules directory. + return mainFile = fileAppendId(file, main, extensions) || + fileResolve(file, main, parentModule, seenDirFiles); + } + }); + + if (resolved && mainFile) { + file = mainFile; + recordChild(parentModule, pkgJsonFile); + // The fileAppendId call above may have returned a directory, + // so continue the loop to make sure we resolve it to a + // non-directory file. + continue; + } + } + + // If we didn't find a `package.json` file, or it didn't have a + // resolvable `.main` property, the only possibility left to + // consider is that this directory contains an `index.js` module. + // This assignment almost always terminates the while loop, because + // there's very little chance `fileIsDirectory(file)` will be true + // for `fileAppendIdPart(file, "index", extensions)`. However, in + // principle it is remotely possible that a file called `index.js` + // could be a directory instead of a file. + file = fileAppendIdPart(file, "index", extensions); + } + + if (file && isString(file.contents)) { + file = fileResolve(file, file.contents, parentModule, seenDirFiles); + } + + recordChild(parentModule, file); + + return file; + }; + + function nodeModulesLookup(file, id, extensions) { + for (var resolved; file && !resolved; file = file.parent) { + resolved = fileIsDirectory(file) && + fileAppendId(file, "node_modules/" + id, extensions); + } + return resolved; + } + + return install; +}; + +if (typeof exports === "object") { + exports.makeInstaller = makeInstaller; +} diff --git a/packages/modules-runtime-hot/modern.js b/packages/modules-runtime-hot/modern.js new file mode 100644 index 0000000000..2445856d2d --- /dev/null +++ b/packages/modules-runtime-hot/modern.js @@ -0,0 +1,25 @@ +meteorInstall = makeInstaller({ + // On the client, make package resolution prefer the "browser" field of + // package.json over the "module" field over the "main" field. + browser: true, + mainFields: ["browser", "module", "main"], + + fallback: function (id, parentId, error) { + if (id && id.startsWith('meteor/')) { + var packageName = id.split('/', 2)[1]; + throw new Error( + 'Cannot find package "' + packageName + '". ' + + 'Try "meteor add ' + packageName + '".' + ); + } + + throw error; + } +}); + +let Module = Package['modules-runtime'].meteorInstall.Module; +meteorInstall.Module.prototype.link = Module.prototype.link; + +// This package should be running after modules-runtime but before modules. +// We want modules to use our patched meteorInstall +Package['modules-runtime'].meteorInstall = meteorInstall; diff --git a/packages/modules-runtime-hot/package.js b/packages/modules-runtime-hot/package.js new file mode 100644 index 0000000000..86db9cba78 --- /dev/null +++ b/packages/modules-runtime-hot/package.js @@ -0,0 +1,23 @@ +Package.describe({ + name: "modules-runtime-hot", + version: "0.13.0", + summary: "Patches modules-runtime to support Hot Module Replacement", + git: "https://github.com/benjamn/install", + documentation: "README.md" +}); + +Package.onUse(function (api) { + api.addFiles("installer.js", [ + "client", + ], { + bare: true + }); + + api.addFiles("modern.js", "modern"); + api.export("meteorInstall", "client"); +}); + +Package.onTest(function (api) { + api.use("tinytest"); + api.use("modules"); // Test modules-runtime via modules. +}); diff --git a/packages/modules/package.js b/packages/modules/package.js index b697b26ec1..185d9ff94f 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.15.0", + version: "0.16.0", summary: "CommonJS module system", documentation: "README.md" }); @@ -12,6 +12,7 @@ Npm.depends({ Package.onUse(function(api) { api.use("modules-runtime"); + api.use("modules-runtime-hot", { weak: true }); api.mainModule("client.js", "client"); api.mainModule("server.js", "server"); api.export("meteorInstall"); diff --git a/packages/mongo/collection.js b/packages/mongo/collection.js index 30d6c82da7..f17d455a6e 100644 --- a/packages/mongo/collection.js +++ b/packages/mongo/collection.js @@ -542,6 +542,7 @@ Object.assign(Mongo.Collection.prototype, { * @param {Object} [options] * @param {Boolean} options.multi True to modify all matching documents; false to only modify one of the matching documents (the default). * @param {Boolean} options.upsert True to insert a document if no matching documents are found. + * @param {Array} options.arrayFilters Optional. Used in combination with MongoDB [filtered positional operator](https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/) to specify which elements to modify in an array field. * @param {Function} [callback] Optional. If present, called with an error object as the first argument and, if no error, the number of affected documents as the second. */ update(selector, modifier, ...optionsAndCallback) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 7f699e47e5..26729521af 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.10.0' + version: '1.10.1' }); Npm.depends({ @@ -38,8 +38,8 @@ Package.onUse(function (api) { ]); // Make weak use of Decimal type on client - api.use('mongo-decimal@0.1.1', 'client', {weak: true}); - api.use('mongo-decimal@0.1.1', 'server'); + api.use('mongo-decimal', 'client', {weak: true}); + api.use('mongo-decimal', 'server'); api.use('underscore', 'server'); diff --git a/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json b/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json index 071d001841..f64c153a89 100644 --- a/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json +++ b/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json @@ -2,9 +2,9 @@ "lockfileVersion": 1, "dependencies": { "decimal.js": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.0.2.tgz", - "integrity": "sha512-qL5tUTXAWjB5cSBfm0V2a4jO5FaDLumCfwc/0f7WaTOT3WU8pIeq2HHrd98eXHtbey4qFWlaPzfml1JWIoO9TQ==" + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", + "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==" } } } diff --git a/packages/non-core/mongo-decimal/package.js b/packages/non-core/mongo-decimal/package.js index 29c590cf28..5170aafcb5 100644 --- a/packages/non-core/mongo-decimal/package.js +++ b/packages/non-core/mongo-decimal/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: "JS simulation of MongoDB Decimal128 type", - version: '0.1.1' + version: '0.1.2' }); Npm.depends({ - "decimal.js": "10.0.2" + "decimal.js": "10.2.1" }); Package.onUse(function (api) { diff --git a/packages/npm-bcrypt/.versions b/packages/npm-bcrypt/.versions deleted file mode 100644 index fe86c99b06..0000000000 --- a/packages/npm-bcrypt/.versions +++ /dev/null @@ -1,5 +0,0 @@ -meteor@1.2.16 -modules@0.7.5 -modules-runtime@0.7.5 -npm-bcrypt@0.9.0 -underscore@1.0.9 diff --git a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json index e93d4b2a87..cb91a9ef22 100644 --- a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json +++ b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json @@ -2,14 +2,14 @@ "lockfileVersion": 1, "dependencies": { "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==" }, "bson": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", - "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", + "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" }, "core-util-is": { "version": "1.0.2", @@ -37,9 +37,9 @@ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "mongodb": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.0.tgz", - "integrity": "sha512-/XWWub1mHZVoqEsUppE0GV7u9kanLvHxho6EvBxQbShXTKYF9trhZC2NzbulRGeG7xMJHD8IOWRcdKx5LPjAjQ==" + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", + "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==" }, "process-nextick-args": { "version": "2.0.1", diff --git a/packages/npm-mongo/package.js b/packages/npm-mongo/package.js index 808137e6ad..4b88f4acf0 100644 --- a/packages/npm-mongo/package.js +++ b/packages/npm-mongo/package.js @@ -3,12 +3,12 @@ Package.describe({ summary: "Wrapper around the mongo npm package", - version: "3.8.0", + version: "3.8.1", documentation: null }); Npm.depends({ - mongodb: "3.6.0" + mongodb: "3.6.2" }); Package.onUse(function (api) { diff --git a/packages/oauth/CHANGELOG.md b/packages/oauth/CHANGELOG.md new file mode 100644 index 0000000000..e3aae0b3d3 --- /dev/null +++ b/packages/oauth/CHANGELOG.md @@ -0,0 +1,16 @@ +## Changelog + +## 1.3.2 - 2020-09-30 +### Breaking changes +- N/A + +### Changes +- Supports `setRedirectUrlWhenLoginStyleIsPopup` option in the settings (`public.packages.oauth.setRedirectUrlWhenLoginStyleIsPopup`) to use `redirectUrl` also in the `popup` loginStyle. + + +## 1.3.1 - 2020-09-29 +### Breaking changes +- N/A + +### Changes +- Supports `disableCheckRedirectUrlOrigin` option in the settings (`packages.oauth.disableCheckRedirectUrlOrigin`) to avoid calling `OAuth._checkRedirectUrlOrigin`, this is important to authenticate using different domains in the same server. diff --git a/packages/oauth/oauth_client.js b/packages/oauth/oauth_client.js index 810c0847ee..c7325e4455 100644 --- a/packages/oauth/oauth_client.js +++ b/packages/oauth/oauth_client.js @@ -45,8 +45,11 @@ OAuth._stateParam = (loginStyle, credentialToken, redirectUrl) => { isCordova: Meteor.isCordova }; - if (loginStyle === 'redirect') + if (loginStyle === 'redirect' || + (Meteor.settings?.public?.packages?.oauth?.setRedirectUrlWhenLoginStyleIsPopup && loginStyle === 'popup') + ) { state.redirectUrl = redirectUrl || ('' + window.location); + } // Encode base64 as not all login services URI-encode the state // parameter when they pass it back to us. diff --git a/packages/oauth/oauth_server.js b/packages/oauth/oauth_server.js index 483b052d3d..9f650a102c 100644 --- a/packages/oauth/oauth_server.js +++ b/packages/oauth/oauth_server.js @@ -390,7 +390,9 @@ OAuth._endOfLoginResponse = (res, details) => { if (details.loginStyle === 'redirect') { redirectUrl = OAuth._stateFromQuery(details.query).redirectUrl; const appHost = Meteor.absoluteUrl(); - if (OAuth._checkRedirectUrlOrigin(redirectUrl)) { + if ( + !Meteor.settings?.packages?.oauth?.disableCheckRedirectUrlOrigin && + OAuth._checkRedirectUrlOrigin(redirectUrl)) { details.error = `redirectUrl (${redirectUrl}` + `) is not on the same host as the app (${appHost})`; redirectUrl = appHost; diff --git a/packages/oauth/package.js b/packages/oauth/package.js index b721645a29..55763a2dc1 100644 --- a/packages/oauth/package.js +++ b/packages/oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Common code for OAuth-based services", - version: "1.3.0" + version: "1.3.2" }); Package.onUse(api => { diff --git a/packages/react-fast-refresh/README.md b/packages/react-fast-refresh/README.md new file mode 100644 index 0000000000..f2aa206a79 --- /dev/null +++ b/packages/react-fast-refresh/README.md @@ -0,0 +1,15 @@ +# react-fast-refresh +[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/react-fast-refresh) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/react-fast-refresh) +*** + +This package updates modified React components in the running app for faster +feedback after changing a file. To be enabled, your app must: + +- Use the `hot-module-replacement` package +- Use React 16.9.0 or newer + +This package is disabled in production. It currently only supports the modern web client. + +Learn more in the [React Fast Refresh docs](https://reactnative.dev/docs/fast-refresh) + +React Fast Refresh can be disabled by setting the `DISABLE_REACT_FAST_REFRESH` environment variable before starting Meteor. diff --git a/packages/react-fast-refresh/client-runtime.js b/packages/react-fast-refresh/client-runtime.js new file mode 100644 index 0000000000..b564ee31ae --- /dev/null +++ b/packages/react-fast-refresh/client-runtime.js @@ -0,0 +1,113 @@ +const enabled = __meteor_runtime_config__.reactFastRefreshEnabled; + +if (enabled && process.env.NODE_ENV !== 'production' && module.hot) { + const runtime = require('react-refresh/runtime'); + + let timeout = null; + function scheduleRefresh() { + if (!timeout) { + timeout = setTimeout(() => { + timeout = null; + runtime.performReactRefresh(); + }, 0); + } + } + + // The react refresh babel plugin only registers functions. For react + // to update other types of exports (such as classes), we have to + // register them + function registerExportsForReactRefresh(moduleId, moduleExports) { + runtime.register(moduleExports, moduleId + ' %exports%'); + + if (moduleExports == null || typeof moduleExports !== 'object') { + // Exit if we can't iterate over exports. + return; + } + + for (var key in moduleExports) { + var desc = Object.getOwnPropertyDescriptor(moduleExports, key); + if (desc && desc.get) { + // Don't invoke getters as they may have side effects. + continue; + } + + var exportValue = moduleExports[key]; + var typeID = moduleId + ' %exports% ' + key; + runtime.register(exportValue, typeID); + } + }; + + // Modules that only export components become React Refresh boundaries. + function isReactRefreshBoundary(moduleExports) { + if (runtime.isLikelyComponentType(moduleExports)) { + return true; + } + if (moduleExports == null || typeof moduleExports !== 'object') { + // Exit if we can't iterate over exports. + return false; + } + + var hasExports = false; + var onlyExportComponents = true; + + for (var key in moduleExports) { + hasExports = true; + + var desc = Object.getOwnPropertyDescriptor(moduleExports, key); + if (desc && desc.get) { + // Don't invoke getters as they may have side effects. + return false; + } + + if (!runtime.isLikelyComponentType(moduleExports[key])) { + onlyExportComponents = false; + } + } + + return hasExports && onlyExportComponents; + }; + + runtime.injectIntoGlobalHook(window); + + window.$RefreshReg$ = () => { }; + window.$RefreshSig$ = () => type => type; + + module.hot.onRequire({ + before(module) { + if (module.loaded) { + // The module was already executed + return; + } + + var prevRefreshReg = window.$RefreshReg$; + var prevRefreshSig = window.$RefreshSig$; + + window.RefreshRuntime = runtime; + window.$RefreshReg$ = (type, _id) => { + const fullId = module.id + ' ' + _id; + RefreshRuntime.register(type, fullId); + } + window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform; + + return { + prevRefreshReg, + prevRefreshSig + }; + }, + after(module, beforeData) { + // TODO: handle modules with errors + if (!beforeData) { + return; + } + + window.$RefreshReg$ = beforeData.prevRefreshReg; + window.$RefreshSig$ = beforeData.prevRefreshSig; + if (isReactRefreshBoundary(module.exports)) { + registerExportsForReactRefresh(module.id, module.exports); + module.hot.accept(); + + scheduleRefresh(); + } + } + }); +} diff --git a/packages/react-fast-refresh/package.js b/packages/react-fast-refresh/package.js new file mode 100644 index 0000000000..13e8fec931 --- /dev/null +++ b/packages/react-fast-refresh/package.js @@ -0,0 +1,20 @@ +Package.describe({ + name: 'react-fast-refresh', + version: '0.1.0', + summary: 'Automatically update React components with HMR', + documentation: 'README.md', + devOnly: true +}); + +Npm.depends({ + 'react-refresh': '0.9.0', + semver: '7.3.4' +}); + +Package.onUse(function (api) { + api.export('ReactFastRefresh'); + api.use('modules'); + api.addFiles('server.js', 'server'); + api.addFiles('client-runtime.js', 'web.browser'); + api.use('hot-module-replacement', { weak: true }); +}); diff --git a/packages/react-fast-refresh/server.js b/packages/react-fast-refresh/server.js new file mode 100644 index 0000000000..1fde5134d8 --- /dev/null +++ b/packages/react-fast-refresh/server.js @@ -0,0 +1,28 @@ + +let enabled = !process.env.DISABLE_REACT_FAST_REFRESH; + +if (enabled) { + try { + // React fast refresh requires react 16.9.0 or newer + const semver = require('semver'); + const pkg = require('react/package.json'); + + enabled = pkg && pkg.version && + semver.gte(pkg.version, '16.9.0'); + } catch (e) { + // If the app doesn't directly depend on react, leave react-refresh + // enabled in case a package or indirect dependency uses react. + } +} + +if (typeof __meteor_runtime_config__ === 'object') { + __meteor_runtime_config__.reactFastRefreshEnabled = enabled; +} + +const babelPlugin = enabled ? + require('react-refresh/babel') : + null; + +ReactFastRefresh = { + babelPlugin, +}; diff --git a/packages/reload/package.js b/packages/reload/package.js index c7269238ca..8263940889 100644 --- a/packages/reload/package.js +++ b/packages/reload/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reload the page while preserving application state.", - version: '1.3.0' + version: '1.3.1' }); Package.onUse(function (api) { diff --git a/packages/reload/reload.js b/packages/reload/reload.js index 4c7486f01d..2fa9f5324a 100644 --- a/packages/reload/reload.js +++ b/packages/reload/reload.js @@ -33,14 +33,29 @@ export const Reload = {}; -var KEY_NAME = 'Meteor_Reload'; +const reloadSettings = + (Meteor.settings && + Meteor.settings.public && + Meteor.settings.public.packages && + Meteor.settings.public.packages.reload) || + {}; -var old_data = {}; +function debug(message, context) { + if (!reloadSettings.debug) { + return; + } + // eslint-disable-next-line no-console + console.log(`[reload] ${message}`, JSON.stringify(context)); +} + +const KEY_NAME = 'Meteor_Reload'; + +let old_data = {}; // read in old data at startup. -var old_json; +let old_json; // This logic for sessionStorage detection is based on browserstate/history.js -var safeSessionStorage = null; +let safeSessionStorage = null; try { // This throws a SecurityError on Chrome if cookies & localStorage are // explicitly disabled @@ -80,24 +95,23 @@ if (safeSessionStorage) { } if (!old_json) old_json = '{}'; -var old_parsed = {}; +let old_parsed = {}; try { old_parsed = JSON.parse(old_json); - if (typeof old_parsed !== "object") { - Meteor._debug("Got bad data on reload. Ignoring."); + if (typeof old_parsed !== 'object') { + Meteor._debug('Got bad data on reload. Ignoring.'); old_parsed = {}; } } catch (err) { - Meteor._debug("Got invalid JSON on reload. Ignoring."); + Meteor._debug('Got invalid JSON on reload. Ignoring.'); } -if (old_parsed.reload && typeof old_parsed.data === "object") { +if (old_parsed.reload && typeof old_parsed.data === 'object') { // Meteor._debug("Restoring reload data."); old_data = old_parsed.data; } - -var providers = []; +let providers = []; ////////// External API ////////// @@ -120,57 +134,89 @@ var providers = []; // (used for OAuth redirect login). // Reload._onMigrate = function (name, callback) { + debug('_onMigrate', {name}); if (!callback) { // name not provided, so first arg is callback. callback = name; name = undefined; + debug('_onMigrate no callback'); } - providers.push({ name: name, callback: callback }); + + providers.push({name: name, callback: callback}); }; // Called by packages when they start up. // Returns the object that was saved, or undefined if none saved. // Reload._migrationData = function (name) { + debug('_migrationData', {name}); return old_data[name]; }; // Options are the same as for `Reload._migrate`. -var pollProviders = function (tryReload, options) { - tryReload = tryReload || function () {}; +const pollProviders = function (tryReload, options) { + debug('pollProviders', {options}); + tryReload = tryReload || function () { + }; options = options || {}; - var migrationData = {}; - var remaining = providers.slice(0); - var allReady = true; - while (remaining.length) { - var p = remaining.shift(); - var status = p.callback(tryReload, options); - if (!status[0]) + const {immediateMigration} = options; + debug( + `pollProviders is ${immediateMigration ? '' : 'NOT '}immediateMigration`, + {options} + ); + const migrationData = {}; + let allReady = true; + providers.forEach(p => { + const {callback, name} = p || {}; + const [ready, data] = callback(tryReload, options) || []; + + debug( + `pollProviders provider ${name || 'unknown'} is ${ + ready ? 'ready' : 'NOT ready' + }`, + {options} + ); + if (!ready) { allReady = false; - if (status.length > 1 && p.name) - migrationData[p.name] = status[1]; - }; - if (allReady || options.immediateMigration) + } + + if (data !== undefined && name) { + migrationData[name] = data; + } + }); + + if (allReady) { + debug('pollProviders allReady', {options, migrationData}); return migrationData; - else - return null; + } + + if (immediateMigration) { + debug('pollProviders immediateMigration', {options, migrationData}); + return migrationData; + } + + return null; }; // Options are: // - immediateMigration: true if the page will be reloaded immediately // regardless of whether packages report that they are ready or not. Reload._migrate = function (tryReload, options) { + debug('_migrate', {options}); // Make sure each package is ready to go, and collect their // migration data - var migrationData = pollProviders(tryReload, options); - if (migrationData === null) + const migrationData = pollProviders(tryReload, options); + if (migrationData === null) { return false; // not ready yet.. + } + let json; try { // Persist the migration data - var json = JSON.stringify({ - data: migrationData, reload: true + json = JSON.stringify({ + data: migrationData, + reload: true, }); } catch (err) { Meteor._debug("Couldn't serialize data for migration", migrationData); @@ -185,7 +231,9 @@ Reload._migrate = function (tryReload, options) { Meteor._debug("Couldn't save data for migration to sessionStorage", err); } } else { - Meteor._debug("Browser does not support sessionStorage. Not saving migration state."); + Meteor._debug( + 'Browser does not support sessionStorage. Not saving migration state.' + ); } return true; @@ -193,7 +241,7 @@ Reload._migrate = function (tryReload, options) { // Allows tests to isolate the list of providers. Reload._withFreshProvidersForTest = function (f) { - var originalProviders = providers.slice(0); + const originalProviders = providers.slice(0); providers = []; try { f(); @@ -208,41 +256,51 @@ Reload._withFreshProvidersForTest = function (f) { // will happen at some point in the future once all of the packages // are ready to migrate. // -var reloading = false; +let reloading = false; Reload._reload = function (options) { + debug('_reload', {options}); options = options || {}; - if (reloading) + if (reloading) { + debug('reloading in progress already', {options}); return; + } reloading = true; function tryReload() { + debug('tryReload'); setTimeout(reload, 1); } function forceBrowserReload() { + debug('forceBrowserReload'); // We'd like to make the browser reload the page using location.replace() // instead of location.reload(), because this avoids validating assets // with the server if we still have a valid cached copy. This doesn't work // when the location contains a hash however, because that wouldn't reload // the page and just scroll to the hash location instead. - if (window.location.hash || window.location.href.endsWith("#")) { + if (window.location.hash || window.location.href.endsWith('#')) { window.location.reload(); - } else { - window.location.replace(window.location.href); + return; } + + window.location.replace(window.location.href); } function reload() { - if (Reload._migrate(tryReload, options)) { - if (Meteor.isCordova) { - WebAppLocalServer.switchToPendingVersion(() => { - forceBrowserReload(); - }); - } else { - forceBrowserReload(); - } + debug('reload'); + if (!Reload._migrate(tryReload, options)) { + return; } + + if (Meteor.isCordova) { + WebAppLocalServer.switchToPendingVersion(() => { + forceBrowserReload(); + }); + return; + } + + forceBrowserReload(); } tryReload(); diff --git a/packages/reload/reload_tests.js b/packages/reload/reload_tests.js index cbe05f6d08..07e5b3c70c 100644 --- a/packages/reload/reload_tests.js +++ b/packages/reload/reload_tests.js @@ -1,9 +1,9 @@ Tinytest.add("reload - migrate", function (test) { Reload._withFreshProvidersForTest(function () { - var ready = false; - + // Simulate the state of migration 1 + let readyStateMigration1 = false; Reload._onMigrate("reload test data 1", function (tryReload, options) { - return [ready, { foo: "bar" }]; + return [readyStateMigration1, { foo: "bar" }]; }); Reload._onMigrate("reload test data 2", function (tryReload, options) { @@ -23,7 +23,7 @@ Tinytest.add("reload - migrate", function (test) { test.equal(data.reload, true); // Now all providers are ready. - ready = true; + readyStateMigration1 = true; test.isTrue(Reload._migrate(function () { })); data = JSON.parse(Reload._getData()); diff --git a/packages/standard-minifier-css/.npm/plugin/minifyStdCSS/npm-shrinkwrap.json b/packages/standard-minifier-css/.npm/plugin/minifyStdCSS/npm-shrinkwrap.json index 303fc30167..740cbbcb85 100644 --- a/packages/standard-minifier-css/.npm/plugin/minifyStdCSS/npm-shrinkwrap.json +++ b/packages/standard-minifier-css/.npm/plugin/minifyStdCSS/npm-shrinkwrap.json @@ -2,29 +2,29 @@ "lockfileVersion": 1, "dependencies": { "@babel/runtime": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", - "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==" + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==" }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" }, "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" }, "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/packages/standard-minifier-css/package.js b/packages/standard-minifier-css/package.js index 5a58798bbd..9fc41c6414 100644 --- a/packages/standard-minifier-css/package.js +++ b/packages/standard-minifier-css/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'standard-minifier-css', - version: '1.6.0', + version: '1.7.2', summary: 'Standard css minifier used with Meteor apps by default.', documentation: 'README.md' }); @@ -8,12 +8,13 @@ Package.describe({ Package.registerBuildPlugin({ name: "minifyStdCSS", use: [ - 'minifier-css' + 'minifier-css', + 'ecmascript' ], npmDependencies: { - "@babel/runtime": "7.6.0", - "source-map": "0.6.1", - "lru-cache": "5.1.1" + "@babel/runtime": "7.11.2", + "source-map": "0.7.3", + "lru-cache": "6.0.0" }, sources: [ 'plugin/minify-css.js' @@ -21,5 +22,6 @@ Package.registerBuildPlugin({ }); Package.onUse(function(api) { + api.use('minifier-css@1.5.3'); api.use('isobuild:minifier-plugin@1.0.0'); }); diff --git a/packages/standard-minifier-css/plugin/minify-css.js b/packages/standard-minifier-css/plugin/minify-css.js index da99c0cc1c..97a3453fc4 100644 --- a/packages/standard-minifier-css/plugin/minify-css.js +++ b/packages/standard-minifier-css/plugin/minify-css.js @@ -1,51 +1,54 @@ -var sourcemap = Npm.require("source-map"); -var createHash = Npm.require("crypto").createHash; -var LRU = Npm.require("lru-cache"); +import sourcemap from "source-map"; +import { createHash } from "crypto"; +import LRU from "lru-cache"; Plugin.registerMinifier({ extensions: ["css"], archMatching: "web" }, function () { - var minifier = new CssToolsMinifier(); + const minifier = new CssToolsMinifier(); return minifier; }); -function CssToolsMinifier () {}; +class CssToolsMinifier { -CssToolsMinifier.prototype.processFilesForBundle = function (files, options) { - var mode = options.minifyMode; + async processFilesForBundle (files, options) { + const mode = options.minifyMode; + + if (! files.length) return; + + const merged = await mergeCss(files); - if (! files.length) return; - - var merged = mergeCss(files); - - if (mode === 'development') { - files[0].addStylesheet({ - data: merged.code, - sourceMap: merged.sourceMap, - path: 'merged-stylesheets.css' - }); - return; - } - - var minifiedFiles = CssTools.minifyCss(merged.code); - - if (files.length) { - minifiedFiles.forEach(function (minified) { + if (mode === 'development') { files[0].addStylesheet({ - data: minified + data: merged.code, + sourceMap: merged.sourceMap, + path: 'merged-stylesheets.css' }); - }); + return; + } + + const minifiedFiles = CssTools.minifyCss(merged.code); + + if (files.length) { + minifiedFiles.forEach(function (minified) { + files[0].addStylesheet({ + data: minified + }); + }); + } } -}; -var mergeCache = new LRU({ +} + + +const mergeCache = new LRU({ max: 100 }); -var hashFiles = Profile("hashFiles", function (files) { - var hash = createHash("sha1"); - var hashes = files.forEach(f => { +const hashFiles = Profile("hashFiles", function (files) { + const hash = createHash("sha1"); + files.forEach(f => { hash.update(f.getSourceHash()).update("\0"); }); return hash.digest("hex"); @@ -59,23 +62,24 @@ function disableSourceMappingURLs(css) { // Lints CSS files and merges them into one file, fixing up source maps and // pulling any @import directives up to the top since the CSS spec does not // allow them to appear in the middle of a file. -var mergeCss = Profile("mergeCss", function (css) { - var hashOfFiles = hashFiles(css); - var merged = mergeCache.get(hashOfFiles); +const mergeCss = Profile("mergeCss", async function (css) { + const hashOfFiles = hashFiles(css); + let merged = mergeCache.get(hashOfFiles); if (merged) { return merged; } // Filenames passed to AST manipulator mapped to their original files - var originals = {}; + const originals = {}; - var cssAsts = css.map(function (file) { - var filename = file.getPathInBundle(); + const cssAsts = css.map(function (file) { + const filename = file.getPathInBundle(); originals[filename] = file; + let ast; try { - var parseOptions = { source: filename, position: true }; - var css = disableSourceMappingURLs(file.getContentsAsString()); - var ast = CssTools.parseCss(css, parseOptions); + const parseOptions = { source: filename, position: true }; + const css = disableSourceMappingURLs(file.getContentsAsString()); + ast = CssTools.parseCss(css, parseOptions); ast.filename = filename; } catch (e) { if (e.reason) { @@ -89,24 +93,23 @@ var mergeCss = Profile("mergeCss", function (css) { file.error({message: e.message}); } - return { type: "stylesheet", stylesheet: { rules: [] }, - filename: filename }; + return { type: "stylesheet", stylesheet: { rules: [] }, filename }; } return ast; }); - var warnCb = function (filename, msg) { + const warnCb = (filename, msg) => { // XXX make this a buildmessage.warning call rather than a random log. // this API would be like buildmessage.error, but wouldn't cause // the build to fail. - console.log(filename + ': warn: ' + msg); + console.log(`${filename}: warn: ${msg}`); }; - var mergedCssAst = CssTools.mergeCssAsts(cssAsts, warnCb); + const mergedCssAst = CssTools.mergeCssAsts(cssAsts, warnCb); // Overwrite the CSS files list with the new concatenated file - var stringifiedCss = CssTools.stringifyCss(mergedCssAst, { + const stringifiedCss = CssTools.stringifyCss(mergedCssAst, { sourcemap: true, // don't try to read the referenced sourcemaps from the input inputSourcemaps: false @@ -126,20 +129,18 @@ var mergeCss = Profile("mergeCss", function (css) { // Compose the concatenated file's source map with source maps from the // previous build step if necessary. - var newMap = Profile.time("composing source maps", function () { - var newMap = new sourcemap.SourceMapGenerator(); - var concatConsumer = new sourcemap.SourceMapConsumer(stringifiedCss.map); - + const newMap = await Profile.time("composing source maps", async function () { + const newMap = new sourcemap.SourceMapGenerator(); + const concatConsumer = await new sourcemap.SourceMapConsumer(stringifiedCss.map); // Create a dictionary of source map consumers for fast access - var consumers = Object.create(null); + const consumers = Object.create(null); - Object.keys(originals).forEach(function (name) { - var file = originals[name]; - var sourceMap = file.getSourceMap(); + await Promise.all(Object.entries(originals).map(async ([name, file]) => { + const sourceMap = file.getSourceMap(); if (sourceMap) { try { - consumers[name] = new sourcemap.SourceMapConsumer(sourceMap); + consumers[name] = await new sourcemap.SourceMapConsumer(sourceMap); } catch (err) { // If we can't apply the source map, silently drop it. // @@ -148,18 +149,18 @@ var mergeCss = Profile("mergeCss", function (css) { // figure out exactly why and fix it, but this will do for now. } } - }); + })); // Maps each original source file name to the SourceMapConsumer that // can provide its content. - var sourceToConsumerMap = Object.create(null); + const sourceToConsumerMap = Object.create(null); // Find mappings from the concatenated file back to the original files - concatConsumer.eachMapping(function (mapping) { - var source = mapping.source; - var consumer = consumers[source]; + concatConsumer.eachMapping((mapping) => { + let { source } = mapping; + const consumer = consumers[source]; - var original = { + let original = { line: mapping.originalLine, column: mapping.originalColumn }; @@ -169,7 +170,7 @@ var mergeCss = Profile("mergeCss", function (css) { // original file. Otherwise, use the mapping of the concatenated file's // source map. if (consumer) { - var newOriginal = consumer.originalPositionFor(original); + const newOriginal = consumer.originalPositionFor(original); // Finding the original position should always be possible (otherwise, // one of the source maps would have incorrect mappings). However, in @@ -199,8 +200,8 @@ var mergeCss = Profile("mergeCss", function (css) { line: mapping.generatedLine, column: mapping.generatedColumn }, - original: original, - source: source + original, + source, }); }); @@ -208,12 +209,14 @@ var mergeCss = Profile("mergeCss", function (css) { // are relatively fast, but not entirely trivial, so it's better to // call them only once per source, rather than calling them every time // we call newMap.addMapping in the loop above. - Object.keys(sourceToConsumerMap).forEach(function (source) { - var consumer = sourceToConsumerMap[source]; - var content = consumer.sourceContentFor(source); + Object.entries(sourceToConsumerMap).forEach(([source, consumer]) => { + const content = consumer.sourceContentFor(source); newMap.setSourceContent(source, content); }); + concatConsumer.destroy(); + Object.values(consumers).forEach(consumer => consumer.destroy()); + return newMap; }); diff --git a/packages/typescript/package.js b/packages/typescript/package.js index 34928b8d30..a646b2bc07 100644 --- a/packages/typescript/package.js +++ b/packages/typescript/package.js @@ -1,19 +1,21 @@ Package.describe({ name: "typescript", - version: "3.7.6", + version: "4.1.2", summary: "Compiler plugin that compiles TypeScript and ECMAScript in .ts and .tsx files", documentation: "README.md" }); Package.registerBuildPlugin({ name: "compile-typescript", - use: ["babel-compiler"], + use: ["babel-compiler", "react-fast-refresh"], sources: ["plugin.js"] }); Package.onUse(function (api) { api.use("isobuild:compiler-plugin@1.0.0"); api.use("babel-compiler"); + api.use('react-fast-refresh'); + // The following api.imply calls should match those in // ../ecmascript/package.js. api.imply("modules"); diff --git a/packages/typescript/plugin.js b/packages/typescript/plugin.js index 35e4ee3a51..350588504e 100644 --- a/packages/typescript/plugin.js +++ b/packages/typescript/plugin.js @@ -4,6 +4,11 @@ Plugin.registerCompiler({ return new TypeScriptCompiler({ react: true, typescript: true, + }, (babelOptions, file) => { + if (file.hmrAvailable() && ReactFastRefresh.babelPlugin) { + babelOptions.plugins = babelOptions.plugins || []; + babelOptions.plugins.push(ReactFastRefresh.babelPlugin); + } }); }); diff --git a/packages/webapp-hashing/package.js b/packages/webapp-hashing/package.js index b6b094371d..af8f7e762d 100644 --- a/packages/webapp-hashing/package.js +++ b/packages/webapp-hashing/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Used internally by WebApp. Knows how to hash programs from manifests.", - version: "1.0.9" + version: "1.1.0" }); Package.onUse(function(api) { diff --git a/packages/webapp-hashing/webapp-hashing.js b/packages/webapp-hashing/webapp-hashing.js index c0c971a223..f2fc190449 100644 --- a/packages/webapp-hashing/webapp-hashing.js +++ b/packages/webapp-hashing/webapp-hashing.js @@ -28,7 +28,7 @@ WebAppHashing.calculateClientHash = hash.update(JSON.stringify(runtimeCfg, 'utf8')); _.each(manifest, function (resource) { - if ((! includeFilter || includeFilter(resource.type)) && + if ((! includeFilter || includeFilter(resource.type, resource.replaceable)) && (resource.where === 'client' || resource.where === 'internal')) { hash.update(resource.path); hash.update(resource.hash); diff --git a/packages/webapp/package.js b/packages/webapp/package.js index 057c4e0026..95733da468 100644 --- a/packages/webapp/package.js +++ b/packages/webapp/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Serves a Meteor app over HTTP", - version: '1.9.1' + version: '1.10.0' }); Npm.depends({"basic-auth-connect": "1.0.0", diff --git a/packages/webapp/webapp_server.js b/packages/webapp/webapp_server.js index bb81e549e7..96f08b34c3 100644 --- a/packages/webapp/webapp_server.js +++ b/packages/webapp/webapp_server.js @@ -267,6 +267,7 @@ Meteor.startup(function () { WebApp.calculateClientHash = WebApp.clientHash = getter("version"); WebApp.calculateClientHashRefreshable = getter("versionRefreshable"); WebApp.calculateClientHashNonRefreshable = getter("versionNonRefreshable"); + WebApp.calculateClientHashReplaceable = getter("versionReplaceable"); WebApp.getRefreshableAssets = getter("refreshableAssets"); }); @@ -738,7 +739,17 @@ function runWebAppServer() { versionRefreshable: () => WebAppHashing.calculateClientHash( manifest, type => type === "css", configOverrides), versionNonRefreshable: () => WebAppHashing.calculateClientHash( - manifest, type => type !== "css", configOverrides), + manifest, (type, replaceable) => type !== "css" && !replaceable, configOverrides), + versionReplaceable: () => WebAppHashing.calculateClientHash( + manifest, (_type, replaceable) => { + if (Meteor.isProduction && replaceable) { + throw new Error('Unexpected replaceable file in production'); + } + + return replaceable + }, + configOverrides + ), cordovaCompatibilityVersions: programJson.cordovaCompatibilityVersions, PUBLIC_SETTINGS, }; diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000000..3a15538a8e --- /dev/null +++ b/prettier.config.js @@ -0,0 +1 @@ +module.exports = require('@quave/eslint-config-quave/prettier.config'); diff --git a/scripts/admin/jsdoc/docdata-jsdoc-template/publish.js b/scripts/admin/jsdoc/docdata-jsdoc-template/publish.js index 11add1405e..736a2488ce 100644 --- a/scripts/admin/jsdoc/docdata-jsdoc-template/publish.js +++ b/scripts/admin/jsdoc/docdata-jsdoc-template/publish.js @@ -96,7 +96,7 @@ } }); - // Callback descriptions are going to be embeded into Function descriptions + // Callback descriptions are going to be embedded into Function descriptions // when they are used as arguments, so we always attach them to reference // them later. var callbacks = helper.find(data, {kind: "typedef"}); diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index e3450a1f5d..72f87b40b8 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.11-rc.0", + "version": "2.0-rc.3", "recommended": false, "official": false, "description": "Meteor" diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index 339adb2cce..9e5c960c28 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.11", + "version": "2.1", "recommended": false, "official": true, "description": "The Official Meteor Distribution" diff --git a/scripts/build-dev-bundle-common.sh b/scripts/build-dev-bundle-common.sh index 19fe60270c..8fad863eec 100644 --- a/scripts/build-dev-bundle-common.sh +++ b/scripts/build-dev-bundle-common.sh @@ -5,10 +5,10 @@ set -u UNAME=$(uname) ARCH=$(uname -m) -NODE_VERSION=12.18.3 +NODE_VERSION=12.21.0 MONGO_VERSION_64BIT=4.2.8 MONGO_VERSION_32BIT=3.2.22 -NPM_VERSION=6.14.6 +NPM_VERSION=6.14.8 # If we built Node from source on Jenkins, this is the build number. NODE_BUILD_NUMBER= diff --git a/scripts/dev-bundle-tool-package.js b/scripts/dev-bundle-tool-package.js index 570183b4be..9fc999a7d4 100644 --- a/scripts/dev-bundle-tool-package.js +++ b/scripts/dev-bundle-tool-package.js @@ -10,12 +10,12 @@ var packageJson = { dependencies: { // Explicit dependency because we are replacing it with a bundled version // and we want to make sure there are no dependencies on a higher version - npm: "6.14.6", + npm: "6.14.8", pacote: "https://github.com/meteor/pacote/tarball/a81b0324686e85d22c7688c47629d4009000e8b8", "node-gyp": "6.0.1", "node-pre-gyp": "0.14.0", - typescript: "3.8.3", - "meteor-babel": "7.9.0", + typescript: "4.1.2", + "meteor-babel": "7.10.6", // Keep the versions of these packages consistent with the versions // found in dev-bundle-server-package.js. "meteor-promise": "0.8.7", @@ -63,7 +63,8 @@ var packageJson = { "@wry/context": "0.4.4", 'lru-cache': '4.1.3', "anser": "1.4.8", - 'xmlbuilder2': '1.3.0' + 'xmlbuilder2': '1.3.0', + "ws": "7.2.5" } }; diff --git a/scripts/generate-dev-bundle.ps1 b/scripts/generate-dev-bundle.ps1 index d1f239f864..bd799c545f 100644 --- a/scripts/generate-dev-bundle.ps1 +++ b/scripts/generate-dev-bundle.ps1 @@ -57,7 +57,7 @@ Function Invoke-Install7ZipApplication { Write-Host "Downloading 7-zip..." -ForegroundColor Magenta $7zMsiPath = Join-Path $dirTemp '7z.msi' # 32-bit, right now. But this does not go in the bundle. - $webclient.DownloadFile("http://www.7-zip.org/a/7z1604.msi", $7zMsiPath) + $webclient.DownloadFile("https://www.7-zip.org/a/7z1604.msi", $7zMsiPath) Write-Host "Installing 7-zip system-wide..." -ForegroundColor Magenta & "msiexec.exe" /i $7zMsiPath /quiet /qn /norestart | Out-Null @@ -69,7 +69,7 @@ Function Invoke-Install7ZipApplication { Function Add-7ZipTool { Write-Host "Downloading 7-zip 'extra'..." -ForegroundColor Magenta $extraArchive = Join-Path $dirTemp 'extra.7z' - $webclient.DownloadFile("http://www.7-zip.org/a/7z1604-extra.7z", $extraArchive) + $webclient.DownloadFile("https://www.7-zip.org/a/7z1604-extra.7z", $extraArchive) $pathToExtract = 'x64/7za.exe' diff --git a/scripts/windows/appveyor/install.ps1 b/scripts/windows/appveyor/install.ps1 index e0063542b1..ced6023ad5 100644 --- a/scripts/windows/appveyor/install.ps1 +++ b/scripts/windows/appveyor/install.ps1 @@ -15,7 +15,7 @@ If ($LASTEXITCODE -ne 0) { throw "Updating submodules failed." } -# The `meteor --get-ready` command is susceptible to EPERM errors, so +# The `meteor --get-ready` command is susceptible to EPERM errors, so # we attempt it three times. $attempt = 3 $success = $false @@ -25,7 +25,7 @@ while ($attempt -gt 0 -and -not $success) { # By redirecting error to host, we avoid a shocking/false error color, # since --get-ready and --version can print (anything) to STDERR and # PowerShell will interpret that as something being terribly wrong. - & "$meteorBat" --get-ready 2>&1 | Write-Host -ForegroundColor Green + & "$meteorBat" --get-ready If ($LASTEXITCODE -eq 0) { $success = $true diff --git a/scripts/windows/download-dev-bundle.ps1 b/scripts/windows/download-dev-bundle.ps1 index 40b4030307..fbc4b83cdd 100644 --- a/scripts/windows/download-dev-bundle.ps1 +++ b/scripts/windows/download-dev-bundle.ps1 @@ -63,3 +63,5 @@ if ("$env:SAVE_DEV_BUNDLE_TARBALL" -ne "") { Write-Host "your environment." Remove-Item -Force $devbundle_zip } + +Write-Host "Done getting the dev_bundle for $PLATFORM version $BUNDLE_VERSION" diff --git a/tools/cli/commands-packages.js b/tools/cli/commands-packages.js index fc82f4fc28..5ae2ad2b81 100644 --- a/tools/cli/commands-packages.js +++ b/tools/cli/commands-packages.js @@ -689,6 +689,8 @@ main.registerCommand({ options: { 'create-track': { type: Boolean }, 'from-checkout': { type: Boolean }, + // It is going to produce a fake error and nothing will be published + 'dry-run': { type: Boolean }, // Normally the publish-release script will complain if the source of // a core package differs in any way from what was previously // published for the current version of the package. However, if the @@ -985,6 +987,15 @@ main.registerCommand({ }); }); + if (options['dry-run']) { + main.captureAndExit("=> Dry run", function () { + buildmessage.error( + "This is not an error but it was just a validation" + + " and nothing was published. Remove --dry-run to publish."); + } + ) + } + // We now have an object of packages that have new versions on disk that // don't exist in the server catalog. Publish them. var unfinishedBuilds = {}; @@ -1139,7 +1150,9 @@ main.registerCommand({ requiresApp: true, options: { 'tree': { type: Boolean }, + 'json': { type: Boolean }, 'weak': { type: Boolean }, + 'details': { type: Boolean }, 'allow-incompatible-update': { type: Boolean } }, catalogRefresh: new catalog.Refresh.OnceAtStart({ ignoreErrors: true }) @@ -1154,8 +1167,25 @@ main.registerCommand({ // No need to display the PackageMapDelta here, since we're about to list all // of the packages anyway! - if (options['tree']) { + const showJson = !!options['json']; + const showTree = !!options['tree']; + + const suffixes = { + topLevel: '(top level)', + expandedAbove: '(expanded above)', + weak: '[weak]', + skipped: 'package skipped', + missing: 'missing?' + } + + if (showJson && showTree) { + throw new Error('can only run for one option,found --json and --tree'); + } + + if (showTree || showJson) { + const jsonOut = showJson && {}; const showWeak = !!options['weak']; + const showDetails = !!options['details']; // Load package details of all used packages (inc. dependencies) const packageDetails = new Map; projectContext.packageMap.eachPackage(function (name, info) { @@ -1172,7 +1202,7 @@ main.registerCommand({ const dontExpand = new Set(topLevelSet.values()); // Recursive function that outputs each package - const printPackage = function (packageToPrint, isWeak, indent1, indent2) { + const printPackage = function ({ packageToPrint, isWeak, indent1, indent2, parent }) { const packageName = packageToPrint.packageName; const depsObj = packageToPrint.dependencies || {}; let deps = Object.keys(depsObj).sort(); @@ -1192,16 +1222,61 @@ main.registerCommand({ const expandedAlready = (deps.length > 0 && dontExpand.has(packageName)); const shouldExpand = (deps.length > 0 && !expandedAlready && !isWeak); - if (indent1 !== '') { - indent1 += (shouldExpand ? '┬' : '─') + ' '; + + // with normal tree display we send the current info to stdout + if (showTree) { + if (indent1 !== '') { + indent1 += (shouldExpand ? '┬' : '─') + ' '; + } + + let suffix = (isWeak ? suffixes.weak : ''); + if (expandedAlready) { + suffix += topLevelSet.has(packageName) + ? ` ${suffixes.topLevel}` + : ` ${suffixes.expandedAbove}` + } + + Console.info(indent1 + packageName + '@' + packageToPrint.version + suffix); } - let suffix = (isWeak ? '[weak]' : ''); - if (expandedAlready) { - suffix += topLevelSet.has(packageName) ? ' (top level)' : ' (expanded above)'; + // with json we add detailed info to the json object + if (showJson) { + if (expandedAlready) { + // on expanded packages we only want to add minimal information to + // keep the json file compact, so we make the value a stirng + if (topLevelSet.has(packageName)) { + parent[packageName] = `${packageToPrint.version}-${suffixes.topLevel}` + } else { + parent[packageName] = `${packageToPrint.version}-${suffixes.expandedAbove}` + } + } else { + // on non-expanded packages we want detailed information but we + // omit falsy values in order to keep the output minimal and readable + const entry = {}; + parent[packageName] = entry; + + const mapInfo = projectContext.packageMap.getInfo(packageName); + const isLocal = mapInfo && mapInfo.kind === 'local'; + + const infoSource = Object.assign({}, showDetails ? packageToPrint : {}, { + version: packageToPrint.version, + local: isLocal, + weak: isWeak, + newerVersion: !isLocal && getNewerVersion(packageName, packageToPrint.version, catalog.official) + }); + + Object.entries(infoSource).forEach(([key, value]) => { + if (value) { + entry[key] = value; + } + }); + + if (shouldExpand) { + entry.dependencies = {}; + } + } } - Console.info(indent1 + packageName + '@' + packageToPrint.version + suffix); if (shouldExpand) { dontExpand.add(packageName); deps.forEach((dep, index) => { @@ -1209,14 +1284,37 @@ main.registerCommand({ const weakRef = references.length > 0 && references.every(r => r.weak); const last = ((index + 1) === deps.length); const child = packageDetails.get(dep); - const newIndent1 = indent2 + (last ? '└─' : '├─'); - const newIndent2 = indent2 + (last ? ' ' : '│ '); - if (child) { - printPackage(child, weakRef, newIndent1, newIndent2); - } else if (weakRef) { - Console.info(newIndent1 + '─ ' + dep + '[weak] package skipped'); - } else { - Console.info(newIndent1 + '─ ' + dep + ' missing?'); + + // with normal tree display we increase indentation + if (showTree) { + const newIndent1 = indent2 + (last ? '└─' : '├─'); + const newIndent2 = indent2 + (last ? ' ' : '│ '); + if (child) { + printPackage({ + packageToPrint: child, + isWeak: weakRef, + indent1: newIndent1, + indent2: newIndent2 + }); + } else if (weakRef) { + Console.info(`${newIndent1}─ ${dep} ${suffixes.weak} ${suffixes.skipped}`); + } else { + Console.info(`${newIndent1}─ ${dep} ${suffixes.missing}`); + } + } + + if (showJson) { + if (child) { + printPackage({ + packageToPrint: child, + isWeak: weakRef, + parent: parent[packageName].dependencies + }); + } else if (weakRef) { + parent[packageName].dependencies[dep] = `${suffixes.weak} ${suffixes.skipped}`; + } else { + parent[packageName].dependencies = suffixes.missing; + } } }); } @@ -1228,10 +1326,23 @@ main.registerCommand({ if (topLevelPackage) { // Force top level packages to be expanded dontExpand.delete(topLevelPackage.packageName); - printPackage(topLevelPackage, false, '', ''); + printPackage({ + packageToPrint: topLevelPackage, + isWeak: false, + indent1: '', + indent2: '', + parent: jsonOut + }) } }); + if (showJson) { + // we can't use Console here, because it pretty prints the output with + // a wrap at 80 chars per line, which causes the json to break if details + // options is active and the package descriptions exceed the limit + console.info(JSON.stringify(jsonOut)); + } + return 0; } diff --git a/tools/cli/commands.js b/tools/cli/commands.js index da9adc786d..c5537997d4 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -505,6 +505,17 @@ main.registerCommand({ /////////////////////////////////////////////////////////////////////////////// // create /////////////////////////////////////////////////////////////////////////////// +const DEFAULT_SKELETON = "react"; +const AVAILABLE_SKELETONS = [ + "apollo", + "bare", + "blaze", + "full", + "minimal", + DEFAULT_SKELETON, + "typescript", + "vue" +]; main.registerCommand({ name: 'create', @@ -516,6 +527,7 @@ main.registerCommand({ bare: { type: Boolean }, minimal: { type: Boolean }, full: { type: Boolean }, + blaze: { type: Boolean }, react: { type: Boolean }, vue: { type: Boolean }, typescript: { type: Boolean }, @@ -763,24 +775,11 @@ main.registerCommand({ toIgnore.push(/(\.html|\.js|\.css)/); } - let skelName = "skel"; - if (options.minimal) { - skelName += "-minimal"; - } else if (options.bare) { - skelName += "-bare"; - } else if (options.full) { - skelName += "-full"; - } else if (options.react) { - skelName += "-react"; - } else if (options.vue) { - skelName += "-vue"; - } else if (options.typescript) { - skelName += "-typescript"; - } else if (options.apollo) { - skelName += "-apollo"; - } - - files.cp_r(files.pathJoin(__dirnameConverted, '..', 'static-assets', skelName), appPath, { + const skeletonExplicitOption = AVAILABLE_SKELETONS.find(skeleton => + !!options[skeleton]); + const skeleton = skeletonExplicitOption || DEFAULT_SKELETON; + files.cp_r(files.pathJoin(__dirnameConverted, '..', 'static-assets', + `skel-${skeleton}`), appPath, { transformFilename: function (f) { return transform(f); }, @@ -883,18 +882,13 @@ main.registerCommand({ Console.options({ indent: 2 })); Console.info(""); - Console.info("When you’re ready to deploy and host your new Meteor application, check out Galaxy:"); + Console.info("When you’re ready to deploy and host your new Meteor application, check out Cloud:"); Console.info( - Console.url("https://www.meteor.com/hosting"), + Console.url("https://www.meteor.com/cloud"), Console.options({ indent: 2 })); - if (! options.bare && - ! options.minimal && - ! options.full && - ! options.react && - ! options.vue && - ! options.typescript) { - // Notify people about --bare, --minimal, --full, --react, --vue, --apollo and --typescript. + if (!!skeletonExplicitOption) { + // Notify people about the skeleton options Console.info([ "", "To start with a different app template, try one of the following:", @@ -908,6 +902,7 @@ main.registerCommand({ cmd("meteor create --vue # to create a basic Vue-based app"); cmd("meteor create --apollo # to create a basic Apollo + React app"); cmd("meteor create --typescript # to create an app using TypeScript and React"); + cmd("meteor create --blaze # to create an app using Blaze"); } Console.info(""); @@ -1437,6 +1432,9 @@ main.registerCommand({ 'deploy-polling-timeout': { type: Number }, 'no-wait': { type: Boolean }, 'cache-build': { type: Boolean }, + free: { type: Boolean }, + plan: { type: String }, + mongo: { type: Boolean } }, allowUnrecognizedOptions: true, requiresApp: function (options) { @@ -1509,6 +1507,10 @@ function deployCommand(options, { rawOptions }) { if (options['deploy-polling-timeout']) { deployPollingTimeoutMs = options['deploy-polling-timeout']; } + let plan = null; + if (options.plan) { + plan = options.plan; + } const isCacheBuildEnabled = !!options['cache-build']; const waitForDeploy = !options['no-wait']; @@ -1517,7 +1519,10 @@ function deployCommand(options, { rawOptions }) { projectContext: projectContext, site: site, settingsFile: options.settings, + free: options.free, + mongo: options.mongo, buildOptions: buildOptions, + plan, rawOptions, deployPollingTimeoutMs, waitForDeploy, @@ -2296,6 +2301,12 @@ main.registerCommand({ 'with-tag': { type: String }, junit: { type: String }, retries: { type: Number, default: 2 }, + // Skip tests, after filter + skip: { type: Number }, + // Limit tests, after filter + limit: { type: Number }, + // Don't run tests, just show the plan after filter, skip and limit + preview: { type: Boolean }, }, hidden: true, catalogRefresh: new catalog.Refresh.Never() @@ -2397,7 +2408,10 @@ main.registerCommand({ clients: clients, junit: options.junit && files.pathResolve(options.junit), 'without-tag': options['without-tag'], - 'with-tag': options['with-tag'] + 'with-tag': options['with-tag'], + skip: options.skip, + limit: options.limit, + preview: options.preview, }); }); diff --git a/tools/cli/default-npm-deps.js b/tools/cli/default-npm-deps.js index 5acf992307..b7a3392434 100644 --- a/tools/cli/default-npm-deps.js +++ b/tools/cli/default-npm-deps.js @@ -13,7 +13,7 @@ export function install(appDir, options) { const needTempPackageJson = ! statOrNull(packageJsonPath); if (needTempPackageJson) { - const { dependencies } = require("../static-assets/skel/package.json"); + const { dependencies } = require("../static-assets/skel-minimal/package.json"); // Write a minimial package.json with the same dependencies as the // default new-app package.json file. diff --git a/tools/cli/help.txt b/tools/cli/help.txt index a0618387e0..fab5ddd333 100644 --- a/tools/cli/help.txt +++ b/tools/cli/help.txt @@ -150,7 +150,7 @@ Options: >>> create Create a new project. -Usage: meteor create [--release ] [--bare|--minimal|--full|--react] +Usage: meteor create [--release ] [--bare|--minimal|--full|--react|--vue|--apollo|--blaze] meteor create [--release ] --example [] meteor create --list meteor create --package [] @@ -159,7 +159,7 @@ Make a subdirectory named if it doesn't exist and create a new Meteor app there. You can pass an absolute path, relative path, or '.' for the current directory. Use the --bare option to create an empty app, or the --minimal option to create an empty app with as few Meteor packages as possible. To scaffold a -more complete app, use the --full option. To create a basic React-based app, +more complete app, use the --full option. To create a basic react-based app, pass the --react option. With the --package option, creates a Meteor package instead of an app. If you're @@ -176,13 +176,17 @@ sample applications. Use --list to see the available examples. There are currently no package examples. Options: - --package Create a new meteor package instead of an app. - --example Example template to use. - --list Show list of available examples. - --bare Create an empty app. - --minimal Create an app with as few Meteor packages as possible. - --full Create a fully scaffolded app. - --react Create a basic React-based app. + --package Create a new meteor package instead of an app. + --example Example template to use. + --list Show list of available examples. + --bare Create an empty app. + --minimal Create an app with as few Meteor packages as possible. + --full Create a fully scaffolded app. + --react Create a basic react-based app, same as default. + --vue Create a basic vue-based app. + --apollo Create a basic apollo-based app. + --typescript Create a basic Typescript React-based app. + --blaze Create a basic blaze-based app. >>> update @@ -289,13 +293,17 @@ Options: List the packages explicitly used by your project. Usage: meteor list meteor list --tree [--weak] + meteor list --json [--weak] [--details] Lists the packages that you have explicitly added to your project. Transitive dependencies are not listed unless you use the --tree option, which outputs a tree showing how packages are referenced. +Use the --json option to output the tree in JSON format. + Options: --weak Show weakly referenced dependencies in the tree. + --details Adds more package details to the JSON output. >>> add-platform Add a platform to this project. @@ -520,6 +528,15 @@ Options: waiting for the deploy to conclude. --cache-build Reuses the build already created if the git commit hash is the same + --free When deploying an app for the first time, you can pass this option + to deploy your app in the Galaxy's free mode. + --plan You can change the app plan by providing this argument with one of + the following values: professional, essentials, or free. Be aware + that this argument overwrites the --free argument. + --mongo If this flag is true and it's not provided a mongo url in the settings + ('galaxy.meteor.com'.env.MONGO_URL), when deploying, Galaxy will create + a database to your app in its shared cluster and will insert the URL in + your app's settings for you. >>> authorized View or change authorized users and organizations for a site. diff --git a/tools/console/console.js b/tools/console/console.js index 46581c2a37..100ba6a415 100644 --- a/tools/console/console.js +++ b/tools/console/console.js @@ -583,6 +583,7 @@ class Console extends ConsoleBase { this._throttledYield = new ThrottledYield(); this.verbose = false; + this._simpleDebug = false; // Legacy helpers this.stdout = Object.create(null); @@ -595,13 +596,18 @@ class Console extends ConsoleBase { this._logThreshold = LEVEL_CODE_INFO; var logspec = process.env.METEOR_LOG; + if (logspec) { logspec = logspec.trim().toLowerCase(); - if (logspec == 'debug') { + if (logspec === 'debug') { this._logThreshold = LEVEL_CODE_DEBUG; } } + if (process.env.METEOR_SIMPLE_DEBUG) { + this._simpleDebug = true; + } + cleanupOnExit((sig) => { this.enableProgressDisplay(false); }); @@ -768,6 +774,17 @@ class Console extends ConsoleBase { this._print(LEVEL_DEBUG, message); } + // Don't use console and so it does not affect tests. + // like this.fullBuffer from matcher. + simpleDebug(...args) { + if (! this._simpleDebug) { + return; + } + + var message = this._format(args); + process.stdout.write( '\n*** simpleDebug ***\n' + message + '\n*** end simpleDebug ***\n'); + } + // By default, Console.debug automatically line wraps the output. // // Takes in an optional Console.options({}) argument at the end, with the diff --git a/tools/cordova/builder.js b/tools/cordova/builder.js index 2af19a016c..2a9f36074a 100644 --- a/tools/cordova/builder.js +++ b/tools/cordova/builder.js @@ -1,5 +1,6 @@ import _ from 'underscore'; import util from 'util'; +import url from 'url'; import path from 'path'; import { Console } from '../console/console.js'; import buildmessage from '../utils/buildmessage.js'; @@ -487,12 +488,14 @@ export class CordovaBuilder { const mobileServerUrl = this.options.mobileServerUrl; + const parsedUrl = url.parse(mobileServerUrl); + const runtimeConfig = { meteorRelease: meteorRelease, gitCommitHash: process.env.METEOR_GIT_COMMIT_HASH || files.findGitCommitHash(applicationPath), ROOT_URL: mobileServerUrl, // XXX propagate it from this.options? - ROOT_URL_PATH_PREFIX: '', + ROOT_URL_PATH_PREFIX: parsedUrl.pathname.replace(/\/$/,"") || '', DDP_DEFAULT_CONNECTION_URL: mobileServerUrl, autoupdate: { versions: { diff --git a/tools/cordova/project.js b/tools/cordova/project.js index 828c565982..d224e2f56d 100644 --- a/tools/cordova/project.js +++ b/tools/cordova/project.js @@ -542,14 +542,15 @@ from Cordova project`, async () => { // Construct a target suitable for 'cordova plugin add' from an id and // version, converting or resolving a URL or path where needed. - targetForPlugin(id, version) { + targetForPlugin(id, version, { usePluginName = false } = {}) { assert(id); assert(version); buildmessage.assertInJob(); if (utils.isUrlWithSha(version)) { - return `${id}@${convertToGitUrl(version)}`; + return usePluginName ? convertToGitUrl(version) : + `${id}@${convertToGitUrl(version)}`; } else if (utils.isUrlWithFileScheme(version)) { // Strip file:// and resolve the path relative to the cordova-build // directory @@ -581,15 +582,29 @@ from Cordova project`, async () => { } } - addPlugin(id, version, config = {}) { - const target = this.targetForPlugin(id, version); + addPlugin(id, version, config = {}, options = {}) { + const { retry = true } = options; + const target = this.targetForPlugin(id, version, options); if (target) { const commandOptions = _.extend(this.defaultOptions, { cli_variables: config, link: utils.isUrlWithFileScheme(version) }); - this.runCommands(`adding plugin ${target} \ + try { + this.runCommands(`adding plugin ${target} \ to Cordova project`, cordova_lib.plugin.bind(undefined, 'add', [target], - commandOptions)); + commandOptions)); + } catch (error) { + if (retry && utils.isUrlWithSha(version)) { + Console.warn(`Cordova plugin add for ${id} failed with plugin id + in the URL with hash, retrying now with plugin name. If this works you + can ignore the error above or you can update your plugin declaration + to use the id from config.xml instead of the name from package.json`); + this.addPlugin(id, version, config, { ...options, + usePluginName: true, retry: false }); + return; + } + throw error; + } } } @@ -775,7 +790,6 @@ perform cordova plugins reinstall`); // @scope/plugin@1.0.0 => { 'com.cordova.plugin': 'scope/plugin' } const installed = this.listInstalledPluginVersions(); const installedPluginsNames = Object.keys(installed); - const installedPluginsVersions = Object.values(installed); const missingPlugins = {}; Object.keys(requiredPlugins).filter(plugin => { diff --git a/tools/fs/files.ts b/tools/fs/files.ts index b5e37a1618..9980d767ff 100644 --- a/tools/fs/files.ts +++ b/tools/fs/files.ts @@ -135,7 +135,7 @@ export function findPackageDir(filepath: string) { // truly unexpected happens). The result value is a string when a Git // revision was successfully resolved, or undefined otherwise. export function findGitCommitHash(path: string) { - return new Promise(resolve => { + return new Promise(resolve => { const appDir = findAppDir(path); if (appDir) { execFile("git", ["rev-parse", "HEAD"], { @@ -330,7 +330,7 @@ export function realpathOrNull(path: string) { } export function rm_recursive_async(path: string) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { rimraf(convertToOSPath(path), (err: Error) => err ? reject(err) : resolve()); @@ -373,12 +373,12 @@ export const blankHash = "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="; // Returns a base64 SHA256 hash representing a tree on disk. It is not sensitive // to modtime, uid/gid, or any permissions bits other than the current-user-exec // bit on normal files. -export function treeHash(root: string, options: { - ignore: (path: string) => boolean; +export function treeHash(root: string, optionsParams: { + ignore?: (path: string) => boolean; }) { - options = { + const options = { ignore() { return false; }, - ...options, + ...optionsParams, }; const hash = require('crypto').createHash('sha256'); @@ -404,6 +404,8 @@ export function treeHash(root: string, options: { } hash.update('file ' + JSON.stringify(relativePath) + ' ' + stat.size + ' ' + fileHash(absPath) + '\n'); + + // @ts-ignore if (stat.mode & 0o100) { hash.update('exec\n'); } @@ -537,6 +539,8 @@ export function cp_r(from: string, to: string, options: { // owner. (This mode will be modified by umask.) We don't copy the // mode *directly* because this function is used by 'meteor create' // which is copying from the read-only tools tree into a writable app. + + // @ts-ignore mode: (stat.mode & 0o100) ? 0o777 : 0o666, }); @@ -1698,6 +1702,8 @@ export function copyFile(from: string, to: string, flags = 0) { // modified by umask.) We don't copy the mode *directly* because this function // is used by 'meteor create' which is copying from the read-only tools tree // into a writable app. + + // @ts-ignore chmod(to, (stat.mode & 0o100) ? 0o777 : 0o666); } } @@ -1711,7 +1717,7 @@ export const rename = isWindowsLikeFilesystem() ? function (from: string, to: st const intervalMs = 50; const timeLimitMs = 1000; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { function attempt() { try { // Despite previous failures, the top-level destination directory diff --git a/tools/fs/safe-watcher.ts b/tools/fs/safe-watcher.ts index c90fa56c18..909dfa6b26 100644 --- a/tools/fs/safe-watcher.ts +++ b/tools/fs/safe-watcher.ts @@ -1,4 +1,4 @@ -import { FSWatcher, Stats } from "fs"; +import { FSWatcher, Stats, BigIntStats } from "fs"; import { Profile } from "../tool-env/profile"; import { statOrNull, @@ -89,7 +89,7 @@ function acquireWatcher(absPath: string, callback: EntryCallback) { } function startNewWatcher(absPath: string): Entry { - let stat: Stats | null = null; + let stat: Stats | BigIntStats | null = null; if (DEDUPLICATE_BY_INO) { stat = statOrNull(absPath); diff --git a/tools/fs/watch.ts b/tools/fs/watch.ts index f473840331..970d38be09 100644 --- a/tools/fs/watch.ts +++ b/tools/fs/watch.ts @@ -1,4 +1,4 @@ -import { Stats, FSWatcher, Dirent } from "fs"; +import { Stats, BigIntStats, FSWatcher, Dirent } from "fs"; import * as files from "./files"; import * as safeWatcher from "./safe-watcher"; import { createHash } from "crypto"; @@ -351,7 +351,7 @@ function readAndStatDirectory(absPath: string) { // Add slashes to the end of directories. const contentsWithSlashes: string[] = []; contents.forEach(entry => { - let stat: Dirent | Stats | null = entry; + let stat: Dirent | Stats | BigIntStats | null = entry; let name = entry.name; if (entry.isSymbolicLink()) { @@ -428,7 +428,7 @@ export class Watcher { watcher: safeWatcher.SafeWatcher | null; // Undefined until we stat the file for the first time, then null // if the file is observed to be missing. - lastStat?: Stats | null + lastStat?: Stats | BigIntStats | null }> = Object.create(null); constructor(options: { diff --git a/tools/index.d.ts b/tools/index.d.ts index 73ead4e9d5..ba79b433a4 100644 --- a/tools/index.d.ts +++ b/tools/index.d.ts @@ -23,4 +23,14 @@ declare global { // func-utils.ts makes usage of this feature displayName?: string; } + + type DiscardPattern = string | RegExp; + + interface Discards { + [packageName: string]: DiscardPattern[]; + } + + interface DiscardsInput { + [packageName: string]: DiscardPattern[] | DiscardPattern; + } } diff --git a/tools/isobuild/builder.js b/tools/isobuild/builder.js index 797dca477c..a02d004bdb 100644 --- a/tools/isobuild/builder.js +++ b/tools/isobuild/builder.js @@ -3,7 +3,7 @@ import {WatchSet, readAndWatchFile, sha1} from '../fs/watch'; import files, { symlinkWithOverwrite, realpath, } from '../fs/files'; -import NpmDiscards from './npm-discards.js'; +import NpmDiscards from './npm-discards'; import {Profile} from '../tool-env/profile'; import { optimisticReadFile, diff --git a/tools/isobuild/bundler.js b/tools/isobuild/bundler.js index fc71b2ca59..88ae89475d 100644 --- a/tools/isobuild/bundler.js +++ b/tools/isobuild/bundler.js @@ -159,7 +159,7 @@ import Builder from './builder.js'; var compilerPluginModule = require('./compiler-plugin.js'); import { JsFile, CssFile } from './minifier-plugin.js'; var meteorNpm = require('./meteor-npm.js'); -import { addToTree } from "./linker.js"; +import { addToTree, File as LinkerFile } from "./linker.js"; var files = require('../fs/files'); var archinfo = require('../utils/archinfo'); @@ -491,7 +491,12 @@ export class NodeModulesDirectory { if (fileStatus && fileStatus.isSymbolicLink()) { // If node_modules/.bin/command is a symlink, determine the // answer by calling isWithinProdPackage(real). - return isWithinProdPackage(files.realpathOrNull(path)); + // guard against broken symlinks (#11241) + const realpath = files.realpathOrNull(path); + if (!realpath) { + throw new Error(`Broken symbolic link encountered at ${path}`); + } + return isWithinProdPackage(realpath); } // If node_modules/.bin/command is not a symlink, then it's hard @@ -572,6 +577,9 @@ class File { // file is not intended to be served over HTTP). this.url = null; + // If updates to this file will be handled with HMR + this.replaceable = options.replaceable; + // A prefix that will be prepended to this.url. // Prefixing is currently restricted to web.cordova URLs. if (options.arch.startsWith("web.") && @@ -838,7 +846,7 @@ class Target { // - addCacheBusters: if true, make all files cacheable by adding // unique query strings to their URLs. unlikely to be of much use // on server targets. - make({packages, minifyMode, addCacheBusters, minifiers}) { + make({packages, minifyMode, addCacheBusters, minifiers, onJsOutputFiles = () => {}}) { buildmessage.assertInCapture(); buildmessage.enterJob("building for " + this.arch, () => { @@ -853,7 +861,22 @@ class Target { }); // Link JavaScript and set up this.js, etc. - this._emitResources(sourceBatches); + this._emitResources(sourceBatches, (outputFiles, sourceBatch, cacheKey) => { + function getFileOutput(file) { + return new LinkerFile(file).getPrelinkedOutput({}); + }; + + onJsOutputFiles( + { + arch: this.arch, + name: sourceBatch.unibuild.pkg.name || null, + files: outputFiles, + hmrAvailable: sourceBatch.hmrAvailable, + cacheKey + }, + getFileOutput + ); + }); // Add top-level Cordova dependencies, which override Cordova // dependencies from packages. @@ -1089,6 +1112,7 @@ class Target { unibuilds: this.unibuilds, arch: this.arch, sourceRoot: this.sourceRoot, + buildMode: this.buildMode, isopackCache: this.isopackCache, linkerCacheDir, scannerCacheDir, @@ -1127,7 +1151,7 @@ class Target { // Process all of the sorted unibuilds (which includes running the JavaScript // linker). - _emitResources(sourceBatches) { + _emitResources(sourceBatches, onJsOutputFiles = () => {}) { buildmessage.assertInJob(); const isWeb = archinfo.matches(this.arch, 'web'); @@ -1183,6 +1207,7 @@ class Target { // Emit the resources const resources = sourceBatch.getResources( jsOutputFilesMap.get(name).files, + (linkCacheKey, jsResources) => onJsOutputFiles(jsResources, sourceBatch, linkCacheKey) ); // First, find all the assets, so that we can associate them with each js @@ -1261,6 +1286,7 @@ class Target { data: resource.data, hash: resource.hash, cacheable: false, + replaceable: resource.type === 'js' && sourceBatch.hmrAvailable }); const relPath = stripLeadingSlash(resource.servePath); @@ -1381,16 +1407,28 @@ class Target { const js = []; function handle(source, dynamic) { + // Allows minifiers to be compatible with HMR without being + // updated to support it. + // In development most minifiers add the file to itself with no + // modifications, and we can safely assume that the file + // is replaceable if the original was. We could provide a way for + // minifiers to set this if they do modify the file in development + // and believe HMR will still update the client correctly. + const possiblyReplaceable = source._minifiedFiles.length === 1 && source._source.replaceable; + source._minifiedFiles.forEach(file => { - if (typeof file.data === "string") { + if (typeof file.data === 'string') { file.data = Buffer.from(file.data, "utf8"); } + const replaceable = possiblyReplaceable && + file.data.equals(source._source.contents()); const newFile = new File({ info: 'minified js', arch, data: file.data, hash: inputHashesByJsFile.get(source), + replaceable }); if (file.sourceMap) { @@ -1684,7 +1722,8 @@ class ClientTarget extends Target { where: "client", type: type, cacheable: file.cacheable, - url: file.url + url: file.url, + replaceable: file.replaceable }; const antiXSSIPrepend = Profile("anti-XSSI header for source-maps", function (sourceMap) { @@ -1760,6 +1799,7 @@ class ClientTarget extends Target { where: manifestItem.where, cacheable: manifestItem.cacheable, hash: manifestItem.hash, + replaceable: manifestItem.replaceable, }); // Now that we've written the module with a source map URL comment @@ -3087,6 +3127,10 @@ Find out more about Meteor at meteor.com. * since they are only safe when the output files from the previous build * are not being used. This can be set to true when it is safe. * + * - onJsOutputFiles Called for each unibuild in a client arch with a list of js files + * that will be linked, and a function to get their prelink output with their closure + * and banner. + * * Returns an object with keys: * - errors: A buildmessage.MessageSet, or falsy if bundling succeeded. * - serverWatchSet: Information about server files and paths that were @@ -3120,6 +3164,7 @@ function bundle({ buildOptions, previousBuilders = Object.create(null), hasCachedBundle, + onJsOutputFiles, allowDelayedClientBuilds = false, forceInPlaceBuild, }) { @@ -3189,7 +3234,8 @@ function bundle({ packages: [app], minifyMode: minifyMode, minifiers: options.minifiers || [], - addCacheBusters: true + addCacheBusters: true, + onJsOutputFiles }); return client; diff --git a/tools/isobuild/compiler-plugin.js b/tools/isobuild/compiler-plugin.js index b8b476d9c4..9e75edaab6 100644 --- a/tools/isobuild/compiler-plugin.js +++ b/tools/isobuild/compiler-plugin.js @@ -113,6 +113,7 @@ export class CompilerPluginProcessor { unibuilds, arch, sourceRoot, + buildMode, isopackCache, linkerCacheDir, scannerCacheDir, @@ -122,6 +123,7 @@ export class CompilerPluginProcessor { unibuilds, arch, sourceRoot, + buildMode, isopackCache, linkerCacheDir, scannerCacheDir, @@ -292,6 +294,12 @@ class InputFile extends buildPluginModule.InputFile { return inputResource.fileOptions || (inputResource.fileOptions = {}); } + hmrAvailable() { + const fileOptions = this.getFileOptions() || {}; + + return this._resourceSlot.hmrAvailable() && !fileOptions.bare; + } + readAndWatchFileWithHash(path) { const sourceBatch = this._resourceSlot.packageSourceBatch; return readAndWatchFileWithHash( @@ -700,6 +708,10 @@ class ResourceSlot { ); } + hmrAvailable() { + return this.packageSourceBatch.hmrAvailable; + } + addStylesheet(options, lazyFinalizer) { if (! this.sourceProcessor) { throw Error("addStylesheet on non-source ResourceSlot?"); @@ -1100,6 +1112,18 @@ export class PackageSourceBatch { self.unibuild.arch ); + const isDevelopment = self.processor.buildMode === 'development'; + const usesHMRPackage = self.unibuild.pkg.name !== "hot-module-replacement" && + self.processor.isopackCache.uses( + self.unibuild.pkg, + "hot-module-replacement", + self.unibuild.arch + ); + const supportedArch = self.unibuild.arch === 'web.browser'; + + self.hmrAvailable = self.useMeteorInstall && isDevelopment + && usesHMRPackage && supportedArch; + // These are the options that should be passed as the second argument // to meteorInstall when modules in this source batch are installed. self.meteorInstallOptions = self.useMeteorInstall ? { @@ -1624,7 +1648,7 @@ export class PackageSourceBatch { // that end up in the program for this package. By this point, it knows what // its dependencies are and what their exports are, so it can set up // linker-style imports and exports. - getResources(jsResources) { + getResources(jsResources, onCacheKey) { buildmessage.assertInJob(); const resources = []; @@ -1633,12 +1657,12 @@ export class PackageSourceBatch { resources.push(...slot.outputResources); }); - resources.push(...this._linkJS(jsResources)); + resources.push(...this._linkJS(jsResources, onCacheKey)); return resources; } - _linkJS(jsResources) { + _linkJS(jsResources, onCacheKey = () => {}) { const self = this; buildmessage.assertInJob(); @@ -1687,6 +1711,7 @@ export class PackageSourceBatch { fileHashes })); const cacheKey = `${cacheKeyPrefix}_${cacheKeySuffix}`; + onCacheKey(cacheKey, jsResources); if (LINKER_CACHE.has(cacheKey)) { if (CACHE_DEBUG) { diff --git a/tools/isobuild/linker.js b/tools/isobuild/linker.js index 2450ca09f7..7652a10eba 100644 --- a/tools/isobuild/linker.js +++ b/tools/isobuild/linker.js @@ -63,7 +63,7 @@ _.extend(Module.prototype, { // servePath: the path where it would prefer to be served if possible addFile: function (inputFile) { var self = this; - self.files.push(new File(inputFile, self)); + self.files.push(new File(inputFile, self.bundleArch)); }, @@ -550,7 +550,7 @@ var writeSymbolTree = function (symbolTree, indent) { // File /////////////////////////////////////////////////////////////////////////////// -function File(inputFile, module) { +export function File(inputFile, arch) { var self = this; // source code for this file (a string) @@ -603,8 +603,8 @@ function File(inputFile, module) { // .jsonData property. self.jsonData = inputFile.jsonData || null; - // The Module containing this file. - self.module = module; + // The arch this file will run in + self.bundleArch = arch; // Options to pass to meteorInstall when this file is installed. // Defined only when the modules package is in use by this module. @@ -827,7 +827,7 @@ const getPrelinkedOutputCached = require("optimism").wrap( return JSON.stringify({ hash: file._inputHash, - arch: file.module.bundleArch, + arch: file.bundleArch, bare: file.bare, servePath: file.servePath, options, @@ -839,7 +839,7 @@ const getPrelinkedOutputCached = require("optimism").wrap( function getOutputWithSourceMapCached(file, servePath, options) { const key = JSON.stringify({ hash: file._inputHash, - arch: file.module.bundleArch, + arch: file.bundleArch, bare: file.bare, servePath: file.servePath, dynamic: file.isDynamic(), diff --git a/tools/isobuild/npm-discards.js b/tools/isobuild/npm-discards.js deleted file mode 100644 index b895a1cec0..0000000000 --- a/tools/isobuild/npm-discards.js +++ /dev/null @@ -1,92 +0,0 @@ -var assert = require("assert"); -var files = require('../fs/files'); -var _ = require("underscore"); - -// This class encapsulates a structured specification of files and -// directories that should be stripped from the node_modules directories -// of Meteor packages during `meteor build`, as requested by calling -// `Npm.discard` in package.js files. -function NpmDiscards() { - assert.ok(this instanceof NpmDiscards); - this.discards = {}; -} - -var NDp = NpmDiscards.prototype; - -// Update the current specification of discarded files with additional -// patterns that should be discarded. See the comment in package-source.js -// about `Npm.strip` for an explanation of what should be passed for the -// `discards` parameter. -NDp.merge = function(discards) { - merge(this.discards, discards); -}; - -function merge(into, from) { - _.each(from, function(fromValue, packageName) { - var intoValue = _.has(into, packageName) && into[packageName]; - if (_.isString(fromValue) || - _.isRegExp(fromValue)) { - if (intoValue) { - intoValue.push(fromValue); - } else { - into[packageName] = [fromValue]; - } - } else if (_.isArray(fromValue)) { - if (intoValue) { - intoValue.push.apply(intoValue, fromValue); - } else { - // Make a defensive copy of any arrays passed to `Npm.strip`. - into[packageName] = fromValue.slice(0); - } - } - }); -} - -NDp.shouldDiscard = function shouldDiscard(candidatePath, isDirectory) { - if (typeof isDirectory === "undefined") { - isDirectory = files.lstat(candidatePath).isDirectory(); - } - - for (var currentPath = candidatePath, parentPath; - (parentPath = files.pathDirname(currentPath)) !== currentPath; - currentPath = parentPath) { - if (files.pathBasename(parentPath) === "node_modules") { - var packageName = files.pathBasename(currentPath); - - if (_.has(this.discards, packageName)) { - var relPath = files.pathRelative(currentPath, candidatePath); - - if (isDirectory) { - relPath = files.pathJoin(relPath, files.pathSep); - } - - return this.discards[packageName].some(function(pattern) { - return matches(pattern, relPath); - }); - } - - // Stop at the first ancestor node_modules directory we find. - break; - } - } - - return false; -}; - -// TODO Improve this. For example we don't currently support wildcard -// string patterns (just use a RegExp if you need that flexibility). -function matches(pattern, relPath) { - if (_.isRegExp(pattern)) { - return relPath.match(pattern); - } - - assert.ok(_.isString(pattern)); - - if (pattern.charAt(0) === files.pathSep) { - return relPath.indexOf(pattern.slice(1)) === 0; - } - - return relPath.indexOf(pattern) !== -1; -} - -module.exports = NpmDiscards; diff --git a/tools/isobuild/npm-discards.ts b/tools/isobuild/npm-discards.ts new file mode 100644 index 0000000000..3ace0e83f2 --- /dev/null +++ b/tools/isobuild/npm-discards.ts @@ -0,0 +1,91 @@ +import * as files from "../fs/files"; + +const hasOwn = Object.prototype.hasOwnProperty; + +// This class encapsulates a structured specification of files and +// directories that should be stripped from the node_modules directories +// of Meteor packages during `meteor build`, as requested by calling +// `Npm.discard` in package.js files. +class NpmDiscards { + private discards: Discards; + + constructor() { + this.discards = {}; + } + + // Update the current specification of discarded files with additional + // patterns that should be discarded. + merge(discards: DiscardsInput): void { + merge(this.discards, discards); + } + + shouldDiscard(candidatePath: string, isDirectory?: boolean): boolean { + if (isDirectory === void 0) { + isDirectory = files.lstat(candidatePath).isDirectory(); + } + + for (let currentPath = candidatePath, parentPath; + (parentPath = files.pathDirname(currentPath)) !== currentPath; + currentPath = parentPath) { + if (files.pathBasename(parentPath) === "node_modules") { + const packageName = files.pathBasename(currentPath); + + if (hasOwn.call(this.discards, packageName)) { + let relPath = files.pathRelative(currentPath, candidatePath); + + if (isDirectory) { + relPath = files.pathJoin(relPath, files.pathSep); + } + + return this.discards[packageName].some(pattern => + matches(pattern, relPath) + ); + } + + // Stop at the first ancestor node_modules directory we find. + break; + } + } + + return false; + } +} + +function merge(into: Discards, from: DiscardsInput): void { + Object.keys(from).forEach((packageName: string) => { + const fromValue = from[packageName]; + const intoValue = hasOwn.call(into, packageName) && into[packageName]; + + if (typeof fromValue === "string" || fromValue instanceof RegExp) { + if (intoValue) { + intoValue.push(fromValue); + } else { + into[packageName] = [fromValue]; + } + + } else if (Array.isArray(fromValue)) { + if (intoValue) { + intoValue.push.apply(intoValue, fromValue); + } else { + // Make a defensive copy of any arrays passed to `Npm.strip`. + into[packageName] = Array.from(fromValue); + } + } + }); +} + +// TODO Improve this. For example we don't currently support wildcard +// string patterns (just use a RegExp if you need that flexibility). +function matches(pattern: DiscardPattern, relPath: string): boolean { + if (pattern instanceof RegExp) { + return pattern.test(relPath); + } + + if (pattern.charAt(0) === files.pathSep) { + return relPath.indexOf(pattern.slice(1)) === 0; + } + + return relPath.includes(pattern); +} + +export default NpmDiscards; diff --git a/tools/isobuild/package-npm.js b/tools/isobuild/package-npm.js index cfc394323d..a2dd10d32c 100644 --- a/tools/isobuild/package-npm.js +++ b/tools/isobuild/package-npm.js @@ -1,6 +1,6 @@ import { ensureOnlyValidVersions } from "../utils/utils.js"; import buildmessage from "../utils/buildmessage.js"; -import NpmDiscards from "./npm-discards.js"; +import NpmDiscards from "./npm-discards"; const nodeRequire = require; @@ -103,6 +103,14 @@ export class PackageNpm { // useragent: ["tests/"] // }); // + // Alternatively, a single string or regular expression can be passed + // instead of an array: + // + // Npm.strip({ + // connect: /*\.wmv$/, + // useragent: "tests/" + // }); + // // This means (1) "remove any files with the `.wmv` extension from // the 'connect' package directory" and (2) "remove the 'tests' // directory from the 'useragent' package directory." diff --git a/tools/isobuild/package-source.js b/tools/isobuild/package-source.js index 0d5af2d078..eec8545ccd 100644 --- a/tools/isobuild/package-source.js +++ b/tools/isobuild/package-source.js @@ -1268,7 +1268,9 @@ _.extend(PackageSource.prototype, { sourceRoot: self.sourceRoot, excludes: anyLevelExcludes, names: sourceReadOptions.names, - include: sourceReadOptions.include + include: sourceReadOptions.include, + // stringify does not work on Set + nodeModulesToRecompile: [...nodeModulesToRecompile], }, (key, value) => { if (_.isRegExp(value)) { return [value.source, value.flags]; diff --git a/tools/isobuild/resolver.ts b/tools/isobuild/resolver.ts index 0092f20fb4..c84c56f29e 100644 --- a/tools/isobuild/resolver.ts +++ b/tools/isobuild/resolver.ts @@ -14,7 +14,7 @@ import { convertToOSPath, convertToPosixPath, } from "../fs/files"; -import { Stats } from "fs"; +import { Stats, BigIntStats } from "fs"; import { wrap } from "optimism"; import { optimisticStatOrNull, @@ -42,7 +42,7 @@ export type ResolverOptions = { } export type Resolution = { - stat: Stats; + stat: Stats | BigIntStats; path: string; packageJsonMap?: Record>; id?: string; @@ -63,7 +63,7 @@ export default class Resolver { private nodeModulesPaths: string[]; private mainFields: string[]; - public statOrNull = optimisticStatOrNull as (path: string) => Stats | null; + public statOrNull = optimisticStatOrNull as (path: string) => Stats | BigIntStats | null; constructor({ sourceRoot, diff --git a/tools/meteor-services/deploy.js b/tools/meteor-services/deploy.js index 08881fa098..c2e7e99422 100644 --- a/tools/meteor-services/deploy.js +++ b/tools/meteor-services/deploy.js @@ -617,7 +617,16 @@ export async function bundleAndDeploy(options) { method: 'POST', operation: 'deploy', site: site, - qs: Object.assign({}, options.rawOptions, settings !== null ? {settings: settings} : {}), + qs: Object.assign( + {}, + options.rawOptions, + settings !== null ? {settings: settings} : {}, + { + free: options.free, + plan: options.plan, + mongo: options.mongo + }, + ), bodyStream: createTarGzStream(pathJoin(buildDir, 'bundle')), expectPayload: ['url'], preflightPassword: preflight.preflightPassword, diff --git a/tools/runners/run-all.js b/tools/runners/run-all.js index 1c46b8ef57..b9ea107fc1 100644 --- a/tools/runners/run-all.js +++ b/tools/runners/run-all.js @@ -7,11 +7,13 @@ const runLog = require('./run-log.js'); const release = require('../packaging/release.js'); const Console = require('../console/console.js').Console; +const crypto = require('crypto'); const Proxy = require('./run-proxy.js').Proxy; const Selenium = require('./run-selenium.js').Selenium; const AppRunner = require('./run-app.js').AppRunner; const MongoRunner = require('./run-mongo.js').MongoRunner; +const HMRServer = require('./run-hmr').HMRServer; const Updater = require('./run-updater.js').Updater; class Runner { @@ -63,12 +65,15 @@ class Runner { }); } + const HMRPath = '/__meteor__hmr__/websocket'; + self.proxy = new Proxy({ listenPort, listenHost: proxyHost, proxyToPort: self.appPort, proxyToHost: appHost, - onFailure + onFailure, + ignoredUrls: [HMRPath] }); buildmessage.capture(function () { @@ -105,6 +110,20 @@ class Runner { mongoUrl = 'no-mongo-server'; } + const hasHotModuleReplacementPackage = packageMap && + packageMap.getInfo('hot-module-replacement') != null; + self.hmrServer = null; + let hmrSecret = null; + if (hasHotModuleReplacementPackage) { + hmrSecret = crypto.randomBytes(64).toString('hex'); + self.hmrServer = new HMRServer({ + proxy: self.proxy, + hmrPath: HMRPath, + secret: hmrSecret, + projectContext: self.projectContext + }); + } + self.updater = new Updater(); self.appRunner = new AppRunner({ @@ -117,7 +136,9 @@ class Runner { rootUrl: self.rootUrl, proxy: self.proxy, noRestartBanner: self.quiet, - cordovaRunner: cordovaRunner + cordovaRunner: cordovaRunner, + hmrServer: self.hmrServer, + hmrSecret }); self.selenium = null; @@ -169,6 +190,14 @@ class Runner { self.updater.start(); } + if (!self.stopped && self.hmrServer) { + self.hmrServer.start(); + + if (!self.quiet && !self.stopped) { + runLog.log("Started HMR server.", { arrow: true }); + } + } + if (! self.stopped) { buildmessage.enterJob({ title: "starting your app" }, function () { self.appRunner.start(); diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index c5aaf49ba3..a702f12279 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -74,6 +74,8 @@ var AppProcess = function (options) { self.testMetadata = options.testMetadata; self.autoRestart = options.autoRestart; + self.hmrSecret = options.hmrSecret; + self.proc = null; self.madeExitCallback = false; }; @@ -224,6 +226,10 @@ _.extend(AppProcess.prototype, { env.METEOR_PRINT_ON_LISTEN = 'true'; + if (self.hmrSecret) { + env.METEOR_HMR_SECRET = self.hmrSecret; + } + return env; }, @@ -376,6 +382,9 @@ var AppRunner = function (options) { self.watchPromise = null; self._promiseResolvers = {}; + self.hmrServer = options.hmrServer; + self.hmrSecret = options.hmrSecret; + // If this promise is set with self.makeBeforeStartPromise, then for the first // run, we will wait on it just before self.appProcess.start() is called. self._beforeStartPromise = null; @@ -576,6 +585,7 @@ _.extend(AppRunner.prototype, { buildOptions: self.buildOptions, hasCachedBundle: !! cachedServerWatchSet, previousBuilders: self.builders, + onJsOutputFiles: self.hmrServer ? self.hmrServer.compare.bind(self.hmrServer) : undefined, // Permit delayed bundling of client architectures if the // console is interactive. allowDelayedClientBuilds: ! Console.isHeadless(), @@ -725,6 +735,9 @@ _.extend(AppRunner.prototype, { inspect: self.inspect, onListen: function () { self.proxy.setMode("proxy"); + if (self.hmrServer) { + self.hmrServer.setAppState("okay"); + } options.onListen && options.onListen(); self._resolvePromise("start"); self._resolvePromise("listen"); @@ -733,6 +746,7 @@ _.extend(AppRunner.prototype, { settings: settings, testMetadata: self.testMetadata, autoRestart: self.autoRestart, + hmrSecret: self.hmrSecret }); if (options.firstRun && self._beforeStartPromise) { @@ -914,6 +928,9 @@ _.extend(AppRunner.prototype, { } self.proxy.setMode("hold"); + if (self.hmrServer) { + self.hmrServer.setAppState("okay"); + } appProcess.stop(); serverWatcher && serverWatcher.stop(); @@ -1001,6 +1018,9 @@ _.extend(AppRunner.prototype, { } }); self.proxy.setMode("errorpage"); + if (self.hmrServer) { + self.hmrServer.setAppState("error"); + } // If onChange wasn't called synchronously (clearing watchPromise), wait // on it. self.watchPromise && self.watchPromise.await(); diff --git a/tools/runners/run-hmr.js b/tools/runners/run-hmr.js new file mode 100644 index 0000000000..c821ecd43f --- /dev/null +++ b/tools/runners/run-hmr.js @@ -0,0 +1,364 @@ +import WS from 'ws'; +import runLog from './run-log.js'; +import crypto from 'crypto'; +import { AssertionError } from 'assert'; +import Anser from "anser"; + +export class HMRServer { + constructor({ proxy, hmrPath, secret, projectContext }) { + this.proxy = proxy; + this.projectContext = projectContext; + + this.hmrPath = hmrPath; + this.secret = secret; + + this.wsServer = null; + this.connByArch = Object.create(null); + this.started = false; + + this.changeSetsByArch = Object.create(null); + + this.maxChangeSets = 300; + this.cacheKeys = Object.create(null); + this.trimmedArchUntil = Object.create(null); + + this.started = false; + } + + start() { + if (!this.proxy.started) { + throw new Error('Proxy must be started before HMR Server'); + } + + this.wsServer = new WS.Server({ + noServer: true, + }); + this.proxy.server.on('upgrade', (req, res, head) => { + if (req.url === this.hmrPath) { + this.wsServer.handleUpgrade(req, res, head, (conn) => { + this._handleWsConn(conn); + }); + } + }); + + this.started = true; + } + + stop() { + this.wsServer.close(); + this.connByArch = Object.create(null); + } + + _handleWsConn(conn) { + let registered = false; + let connArch = null; + conn.on('message', (_message) => { + const message = JSON.parse(_message); + + switch (message.type) { + case 'register': { + const { arch, appId, secret = '' } = message; + + if (appId !== this.projectContext.appIdentifier) { + // A different app is trying to request changes + conn.send(JSON.stringify({ + type: 'register-failed', + reason: 'wrong-app' + })); + } + if ( + secret.length !== this.secret.length || + !crypto.timingSafeEqual(Buffer.from(secret), Buffer.from(this.secret)) + ) { + conn.send(JSON.stringify({ + type: 'register-failed', + reason: 'wrong-secret' + })); + conn.close(); + return; + } + + this.connByArch[arch] = this.connByArch[arch] || []; + this.connByArch[arch].push(conn); + connArch = arch; + registered = true; + break; + } + + case 'request-changes': { + if (!registered) { + // Might have sent the wrong secret or be the wrong app + // Even if we closed the connection, it might still handle + // this message. + return; + } + const { after, arch } = message; + + const trimmedUntil = this.trimmedArchUntil[arch] || 0; + if (trimmedUntil > after) { + // We've removed changeSets needed for the client to update with HMR + conn.send( + JSON.stringify({ + type: 'changes', + changeSets: [ + { reloadable: false } + ] + }) + ); + return; + } + + const archChangeSets = this.changeSetsByArch[arch] || []; + const newChanges = archChangeSets.filter(({ linkedAt }) => { + return linkedAt > after; + }); + + conn.send(JSON.stringify({ + type: 'changes', + changeSets: newChanges + })); + + break; + } + + default: + throw new Error(`Unknown HMR message ${message.type}`); + } + }); + + // TODO: should use pings to detect disconnected sockets + conn.on('close', () => { + if (!connArch) { + return; + } + + const archConns = this.connByArch[connArch] || []; + const index = archConns.indexOf(conn); + if (index > -1) { + archConns.splice( + index, + 1 + ); + } + }); + } + + _sendAll(message) { + Object.values(this.connByArch).forEach(conns => { + conns.forEach(conn => { + conn.send(JSON.stringify(message)); + }); + }); + } + + setAppState(state) { + if (state === 'error') { + const lines = runLog.getLog().map(line => { + return Anser.ansiToHtml(Anser.escapeForHtml(line.message)) + }); + this._sendAll({ + type: 'app-state', + state: 'error', + log: lines + }); + } else if (state === 'okay') { + this._sendAll({ + type: 'app-state', + state: 'okay' + }); + } + } + + compare({ name, arch, hmrAvailable, files, cacheKey }, getFileOutput) { + this.changeSetsByArch[arch] = this.changeSetsByArch[arch] || []; + const previousCacheKey = this.cacheKeys[`${arch}-${name}`]; + + if (previousCacheKey === cacheKey) { + return; + } + + this.cacheKeys[`${arch}-${name}`] = cacheKey; + const previous = this.findLastChangeset(name, arch) || {}; + + if (!hmrAvailable) { + this.changeSetsByArch[arch].push({ + name, + reloadable: false, + cacheKey, + // TODO: use more accurate name + linkedAt: Date.now() + }); + this._trimChangeSets(arch); + return; + } + + const { + addedFiles, + changedFiles, + removedFilePaths, + unreloadable, + onlyReplaceableChanges, + fileHashes + } = this.compareFiles( + previous.fileHashes, + previous.unreloadableHashes, + files + ); + + const couldCompare = !!previous.fileHashes + const reloadable = couldCompare && + onlyReplaceableChanges && + removedFilePaths.length === 0; + + function saveFileDetails(file) { + return { + content: getFileOutput(file).toStringWithSourceMap({}), + path: file.absModuleId, + meteorInstallOptions: file.meteorInstallOptions + }; + } + + const result = { + fileHashes, + unreloadableHashes: unreloadable, + reloadable, + addedFiles: reloadable ? addedFiles.map(saveFileDetails) : [], + changedFiles: reloadable ? changedFiles.map(saveFileDetails) : [], + linkedAt: Date.now(), + id: this._createId(), + name + }; + + // TODO: we should also store the latest change set + // for each arch and name someplace else so it doesn't + // get removed when trimming changesets + this.changeSetsByArch[arch].push(result); + this._trimChangeSets(arch); + + // Try to do HMR without waiting for the build to finish + // If it fails, it will retry after the build finishes so + // it can fall back to hot code push + if (this.connByArch[arch]) { + this.connByArch[arch].forEach(conn => { + conn.send(JSON.stringify({ + type: 'changes', + changeSets: [result], + eager: true + })); + }); + } + return; + } + + _trimChangeSets(arch) { + if (this.changeSetsByArch[arch].length > this.maxChangeSets) { + const removed = this.changeSetsByArch[arch].splice( + 0, + this.changeSetsByArch[arch].length - this.maxChangeSets + ); + this.trimmedArchUntil[arch] = removed[removed.length - 1].linkedAt; + } + } + + _createId() { + return `${Date.now()}-${Math.random()}`; + } + + _checkReloadable(file) { + return file.absModuleId && + !file.bare && + // TODO: support jsonData + !file.jsonData && + file.meteorInstallOptions + } + + compareFiles(previousHashes = new Map(), previousUnreloadable = [], currentFiles) { + const unreloadable = []; + const currentHashes = new Map(); + const unseenModules = new Map(previousHashes); + + const changedFiles = []; + const addedFiles = []; + let onlyReplaceableChanges = true; + + currentFiles.forEach(file => { + let fileConfig; + let ignoreHash = false; + + if (file.targetPath !== file.sourcePath && file.implicit) { + // The import scanner created this file as an alias to the target path + // This file's content does not change when the hash does, only the + // content of the new file created at the target path. + ignoreHash = true; + fileConfig = JSON.stringify({ + implicit: file.implicit, + sourcePath: file.sourcePath, + targetPath: file.targetPath + }); + } else { + fileConfig = JSON.stringify({ + meteorInstallOptions: file.meteorInstallOptions, + absModuleId: file.absModuleId, + sourceMap: !!file.sourceMap, + mainModule: file.mainModule, + imported: file.imported, + alias: file.alias, + lazy: file.lazy, + bare: file.bare + }) + } + + if ( + !this._checkReloadable(file) + ) { + unreloadable.push(`${fileConfig}-${file._inputHash}`); + return; + } + + currentHashes.set(file.absModuleId, { + inputHash: file._inputHash, + config: fileConfig + }); + + const { + inputHash: previousInputHash, + config: previousConfig + } = previousHashes.get(file.absModuleId) || {}; + + if (!previousInputHash) { + addedFiles.push(file); + } else if (previousConfig !== fileConfig) { + onlyReplaceableChanges = false; + } else if (!ignoreHash && previousInputHash !== file._inputHash) { + changedFiles.push(file); + } + + unseenModules.delete(file.absModuleId); + }); + + const removedFilePaths = Array.from(unseenModules.keys()); + if (onlyReplaceableChanges) { + const unreloadableChanged = unreloadable.length !== previousUnreloadable.length || + unreloadable.some((hash, i) => hash !== previousUnreloadable[i]); + onlyReplaceableChanges = !unreloadableChanged; + } + + return { + fileHashes: currentHashes, + addedFiles, + changedFiles, + removedFilePaths, + unreloadable, + onlyReplaceableChanges, + }; + } + + findLastChangeset(name, arch) { + const changeSets = this.changeSetsByArch[arch] || []; + for (let i = changeSets.length - 1; i >= 0; i--) { + if (changeSets[i].name === name) { + return changeSets[i]; + } + } + } +} diff --git a/tools/runners/run-mongo.js b/tools/runners/run-mongo.js index ed4e7a3ff1..aa5b19abe9 100644 --- a/tools/runners/run-mongo.js +++ b/tools/runners/run-mongo.js @@ -753,7 +753,7 @@ var launchMongo = function (options) { initiateReplSetAndWaitForReady(); if (!stopped) { // Write down that we configured the database properly. - files.writeFile(portFile, options.port); + files.writeFile(portFile, ''+options.port); } } } @@ -854,7 +854,6 @@ _.extend(MRp, { // shouldn't annoy the user by telling it that we couldn't start up. self.suppressExitMessage = true; } - self.handle = launchMongo({ projectLocalDir: self.projectLocalDir, port: self.port, diff --git a/tools/runners/run-proxy.js b/tools/runners/run-proxy.js index 3aa0513072..11590d53cd 100644 --- a/tools/runners/run-proxy.js +++ b/tools/runners/run-proxy.js @@ -2,7 +2,8 @@ var Anser = require("anser"); var _ = require('underscore'); var runLog = require('./run-log.js'); -// options: listenPort, proxyToPort, proxyToHost, onFailure +// options: listenPort, proxyToPort, proxyToHost, +// onFailure, ignoredUrls var Proxy = function (options) { var self = this; @@ -12,6 +13,7 @@ var Proxy = function (options) { self.proxyToPort = options.proxyToPort; self.proxyToHost = options.proxyToHost || '127.0.0.1'; self.onFailure = options.onFailure || function () {}; + self.ignoredUrls = options.ignoredUrls || []; self.mode = "hold"; self.httpQueue = []; // keys: req, res @@ -47,11 +49,19 @@ _.extend(Proxy.prototype, { var server = self.server = http.createServer(function (req, res) { // Normal HTTP request + if (self.ignoredUrls.includes(req.url)) { + return; + } + self.httpQueue.push({ req: req, res: res }); self._tryHandleConnections(); }); self.server.on('upgrade', function (req, socket, head) { + if (self.ignoredUrls.includes(req.url)) { + return; + } + // Websocket connection self.websocketQueue.push({ req: req, socket: socket, head: head }); self._tryHandleConnections(); diff --git a/tools/static-assets/server/mini-files.ts b/tools/static-assets/server/mini-files.ts index 39684b361f..e0bc0ab9fb 100644 --- a/tools/static-assets/server/mini-files.ts +++ b/tools/static-assets/server/mini-files.ts @@ -14,7 +14,7 @@ import { release, EOL } from "os"; // (Windows Subsystem for Linux) even if it otherwise looks like we're on Unix. // https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364 export function isWindowsLikeFilesystem() { - return process.platform === "win32" || release().indexOf("Microsoft") >= 0; + return process.platform === "win32" || release().toLowerCase().includes("microsoft"); } export function toPosixPath(p: string, partialPath: boolean = false) { diff --git a/tools/static-assets/skel-apollo/.meteor/packages b/tools/static-assets/skel-apollo/.meteor/packages index ed6cce950a..caa775ee6f 100644 --- a/tools/static-assets/skel-apollo/.meteor/packages +++ b/tools/static-assets/skel-apollo/.meteor/packages @@ -15,6 +15,7 @@ es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code typescript # Enable TypeScript syntax in .ts and .tsx modules shell-server # Server-side component of the `meteor shell` command +hot-module-replacement # Update client in development without reloading the page static-html # Define static page content in .html files apollo # Basic Apollo integration for Meteor apps diff --git a/tools/static-assets/skel-apollo/imports/ui/App.jsx b/tools/static-assets/skel-apollo/imports/ui/App.jsx index 4b1621d576..7ebf0cb3a0 100644 --- a/tools/static-assets/skel-apollo/imports/ui/App.jsx +++ b/tools/static-assets/skel-apollo/imports/ui/App.jsx @@ -1,19 +1,23 @@ import React from 'react'; -import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client'; +import { InMemoryCache, ApolloProvider, ApolloClient, ApolloLink } from '@apollo/client'; +import { BatchHttpLink } from '@apollo/client/link/batch-http' +// import { MeteorAccountsLink } from 'meteor/apollo' import { Hello } from './Hello.jsx'; import { Info } from './Info.jsx'; +const cache = new InMemoryCache().restore(window.__APOLLO_STATE__); + +const link = ApolloLink.from([ + // MeteorAccountsLink(), + new BatchHttpLink({ + uri: '/graphql' + }) +]); + const client = new ApolloClient({ uri: '/graphql', - cache: new InMemoryCache(), - /* Uncomment this for accounts use - request: operation => - operation.setContext(() => ({ - headers: { - authorization: Accounts._storedLoginToken() - } - })) - */ + cache, + link, }); export const App = () => ( diff --git a/tools/static-assets/skel-apollo/package.json b/tools/static-assets/skel-apollo/package.json index 3954108e95..7570e30d88 100644 --- a/tools/static-assets/skel-apollo/package.json +++ b/tools/static-assets/skel-apollo/package.json @@ -8,12 +8,12 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@apollo/client": "^3.1.1", - "@babel/runtime": "^7.10.5", + "@apollo/client": "^3.1.5", + "@babel/runtime": "^7.11.2", "apollo-boost": "^0.4.9", - "apollo-server-express": "^2.16.1", + "apollo-server-express": "^2.17.0", "graphql": "^15.3.0", - "meteor-node-stubs": "^1.0.0", + "meteor-node-stubs": "^1.0.1", "react": "^16.13.1", "react-dom": "^16.13.1" }, diff --git a/tools/static-assets/skel-apollo/server/apollo.js b/tools/static-assets/skel-apollo/server/apollo.js index fa40ecdaa2..77b5ac4b9f 100644 --- a/tools/static-assets/skel-apollo/server/apollo.js +++ b/tools/static-assets/skel-apollo/server/apollo.js @@ -21,11 +21,5 @@ const server = new ApolloServer({ server.applyMiddleware({ app: WebApp.connectHandlers, - path: '/graphql' -}); - -WebApp.connectHandlers.use('/graphql', (req, res) => { - if (req.method === 'GET') { - res.end(); - } + cors: true }); diff --git a/tools/static-assets/skel-bare/package.json b/tools/static-assets/skel-bare/package.json index 5f95e477c6..2b970219fd 100644 --- a/tools/static-assets/skel-bare/package.json +++ b/tools/static-assets/skel-bare/package.json @@ -5,7 +5,7 @@ "start": "meteor run" }, "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.11.2", "meteor-node-stubs": "^1.0.1" } } diff --git a/tools/static-assets/skel/.gitignore b/tools/static-assets/skel-blaze/.gitignore similarity index 100% rename from tools/static-assets/skel/.gitignore rename to tools/static-assets/skel-blaze/.gitignore diff --git a/examples/other/client-info/.meteor/.gitignore b/tools/static-assets/skel-blaze/.meteor/.gitignore similarity index 100% rename from examples/other/client-info/.meteor/.gitignore rename to tools/static-assets/skel-blaze/.meteor/.gitignore diff --git a/tools/static-assets/skel/.meteor/packages b/tools/static-assets/skel-blaze/.meteor/packages similarity index 100% rename from tools/static-assets/skel/.meteor/packages rename to tools/static-assets/skel-blaze/.meteor/packages diff --git a/examples/other/parties/.meteor/platforms b/tools/static-assets/skel-blaze/.meteor/platforms similarity index 100% rename from examples/other/parties/.meteor/platforms rename to tools/static-assets/skel-blaze/.meteor/platforms diff --git a/tools/static-assets/skel/client/main.css b/tools/static-assets/skel-blaze/client/main.css similarity index 100% rename from tools/static-assets/skel/client/main.css rename to tools/static-assets/skel-blaze/client/main.css diff --git a/tools/static-assets/skel/client/main.html b/tools/static-assets/skel-blaze/client/main.html similarity index 100% rename from tools/static-assets/skel/client/main.html rename to tools/static-assets/skel-blaze/client/main.html diff --git a/tools/static-assets/skel/client/main.js b/tools/static-assets/skel-blaze/client/main.js similarity index 100% rename from tools/static-assets/skel/client/main.js rename to tools/static-assets/skel-blaze/client/main.js diff --git a/tools/static-assets/skel/package.json b/tools/static-assets/skel-blaze/package.json similarity index 94% rename from tools/static-assets/skel/package.json rename to tools/static-assets/skel-blaze/package.json index f8f2793e57..61bcd56b35 100644 --- a/tools/static-assets/skel/package.json +++ b/tools/static-assets/skel-blaze/package.json @@ -8,7 +8,7 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.10.4", + "@babel/runtime": "^7.11.2", "jquery": "^3.5.1", "meteor-node-stubs": "^1.0.1" }, diff --git a/tools/static-assets/skel/server/main.js b/tools/static-assets/skel-blaze/server/main.js similarity index 100% rename from tools/static-assets/skel/server/main.js rename to tools/static-assets/skel-blaze/server/main.js diff --git a/tools/static-assets/skel/tests/main.js b/tools/static-assets/skel-blaze/tests/main.js similarity index 100% rename from tools/static-assets/skel/tests/main.js rename to tools/static-assets/skel-blaze/tests/main.js diff --git a/tools/static-assets/skel-full/package.json b/tools/static-assets/skel-full/package.json index b942252d79..6a7d7a5c0a 100644 --- a/tools/static-assets/skel-full/package.json +++ b/tools/static-assets/skel-full/package.json @@ -6,7 +6,7 @@ "test": "meteor test --once --driver-package meteortesting:mocha" }, "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.11.2", "jquery": "^3.5.1", "meteor-node-stubs": "^1.0.1" }, diff --git a/tools/static-assets/skel-minimal/package.json b/tools/static-assets/skel-minimal/package.json index e4ab0c3f33..ab8fbad718 100644 --- a/tools/static-assets/skel-minimal/package.json +++ b/tools/static-assets/skel-minimal/package.json @@ -8,7 +8,7 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.11.2", "meteor-node-stubs": "^1.0.1" }, "meteor": { diff --git a/tools/static-assets/skel-react/.meteor/packages b/tools/static-assets/skel-react/.meteor/packages index 3319ee0005..72de92e77b 100644 --- a/tools/static-assets/skel-react/.meteor/packages +++ b/tools/static-assets/skel-react/.meteor/packages @@ -15,6 +15,7 @@ es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code typescript # Enable TypeScript syntax in .ts and .tsx modules shell-server # Server-side component of the `meteor shell` command +hot-module-replacement # Update client in development without reloading the page autopublish # Publish all data to the clients (for prototyping) insecure # Allow all DB writes from clients (for prototyping) diff --git a/tools/static-assets/skel-react/package.json b/tools/static-assets/skel-react/package.json index e5eb581cb5..e3b8f06f69 100644 --- a/tools/static-assets/skel-react/package.json +++ b/tools/static-assets/skel-react/package.json @@ -8,7 +8,7 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.11.2", "meteor-node-stubs": "^1.0.1", "react": "^16.13.1", "react-dom": "^16.13.1" diff --git a/tools/static-assets/skel-typescript/.meteor/packages b/tools/static-assets/skel-typescript/.meteor/packages index 3319ee0005..72de92e77b 100644 --- a/tools/static-assets/skel-typescript/.meteor/packages +++ b/tools/static-assets/skel-typescript/.meteor/packages @@ -15,6 +15,7 @@ es5-shim # ECMAScript 5 compatibility for older browsers ecmascript # Enable ECMAScript2015+ syntax in app code typescript # Enable TypeScript syntax in .ts and .tsx modules shell-server # Server-side component of the `meteor shell` command +hot-module-replacement # Update client in development without reloading the page autopublish # Publish all data to the clients (for prototyping) insecure # Allow all DB writes from clients (for prototyping) diff --git a/tools/static-assets/skel-typescript/package.json b/tools/static-assets/skel-typescript/package.json index 9fbd619ca3..976e5c8d12 100644 --- a/tools/static-assets/skel-typescript/package.json +++ b/tools/static-assets/skel-typescript/package.json @@ -8,17 +8,17 @@ "visualize": "meteor --production --extra-packages bundle-visualizer" }, "dependencies": { - "@babel/runtime": "^7.10.5", + "@babel/runtime": "^7.11.2", "meteor-node-stubs": "^1.0.1", "react": "^16.13.1", "react-dom": "^16.13.1" }, "devDependencies": { - "@types/meteor": "^1.4.48", - "@types/mocha": "^8.0.0", - "@types/react": "^16.9.43", + "@types/meteor": "^1.4.49", + "@types/mocha": "^8.0.3", + "@types/react": "^16.9.49", "@types/react-dom": "^16.9.8", - "typescript": "^3.9.7" + "typescript": "^4.0.2" }, "meteor": { "mainModule": { diff --git a/tools/static-assets/skel-vue/src/main.html b/tools/static-assets/skel-vue/client/main.html similarity index 100% rename from tools/static-assets/skel-vue/src/main.html rename to tools/static-assets/skel-vue/client/main.html diff --git a/tools/static-assets/skel-vue/src/client.js b/tools/static-assets/skel-vue/client/main.js similarity index 53% rename from tools/static-assets/skel-vue/src/client.js rename to tools/static-assets/skel-vue/client/main.js index 835acaec7b..665c6aa1b1 100644 --- a/tools/static-assets/skel-vue/src/client.js +++ b/tools/static-assets/skel-vue/client/main.js @@ -1,8 +1,8 @@ import Vue from 'vue' -import './plugins' +import '../imports/ui/plugins' -import App from './App.vue' +import App from '../imports/ui/App.vue' Meteor.startup(() => { new Vue({ diff --git a/tools/static-assets/skel-vue/src/collections/Links.js b/tools/static-assets/skel-vue/imports/api/collections/Links.js similarity index 100% rename from tools/static-assets/skel-vue/src/collections/Links.js rename to tools/static-assets/skel-vue/imports/api/collections/Links.js diff --git a/tools/static-assets/skel-vue/src/collections/Links.tests.js b/tools/static-assets/skel-vue/imports/api/collections/Links.tests.js similarity index 95% rename from tools/static-assets/skel-vue/src/collections/Links.tests.js rename to tools/static-assets/skel-vue/imports/api/collections/Links.tests.js index 0bc5b437dd..ce178512d0 100644 --- a/tools/static-assets/skel-vue/src/collections/Links.tests.js +++ b/tools/static-assets/skel-vue/imports/api/collections/Links.tests.js @@ -4,7 +4,7 @@ import { Meteor } from 'meteor/meteor'; import { assert } from 'chai'; -import Links from './links.js'; +import Links from './Links.js'; if (Meteor.isServer) { describe('links collection', function () { diff --git a/tools/static-assets/skel-vue/src/fixtures.js b/tools/static-assets/skel-vue/imports/api/fixtures.js similarity index 100% rename from tools/static-assets/skel-vue/src/fixtures.js rename to tools/static-assets/skel-vue/imports/api/fixtures.js diff --git a/tools/static-assets/skel-vue/src/methods/createLink.js b/tools/static-assets/skel-vue/imports/api/methods/createLink.js similarity index 100% rename from tools/static-assets/skel-vue/src/methods/createLink.js rename to tools/static-assets/skel-vue/imports/api/methods/createLink.js diff --git a/tools/static-assets/skel-vue/src/methods/createLink.tests.js b/tools/static-assets/skel-vue/imports/api/methods/createLink.tests.js similarity index 100% rename from tools/static-assets/skel-vue/src/methods/createLink.tests.js rename to tools/static-assets/skel-vue/imports/api/methods/createLink.tests.js diff --git a/tools/static-assets/skel-vue/src/methods/index.js b/tools/static-assets/skel-vue/imports/api/methods/index.js similarity index 100% rename from tools/static-assets/skel-vue/src/methods/index.js rename to tools/static-assets/skel-vue/imports/api/methods/index.js diff --git a/tools/static-assets/skel-vue/src/publications/index.js b/tools/static-assets/skel-vue/imports/api/publications/index.js similarity index 100% rename from tools/static-assets/skel-vue/src/publications/index.js rename to tools/static-assets/skel-vue/imports/api/publications/index.js diff --git a/tools/static-assets/skel-vue/src/publications/links.js b/tools/static-assets/skel-vue/imports/api/publications/links.js similarity index 100% rename from tools/static-assets/skel-vue/src/publications/links.js rename to tools/static-assets/skel-vue/imports/api/publications/links.js diff --git a/tools/static-assets/skel-vue/src/publications/links.tests.js b/tools/static-assets/skel-vue/imports/api/publications/links.tests.js similarity index 100% rename from tools/static-assets/skel-vue/src/publications/links.tests.js rename to tools/static-assets/skel-vue/imports/api/publications/links.tests.js diff --git a/tools/static-assets/skel-vue/src/App.vue b/tools/static-assets/skel-vue/imports/ui/App.vue similarity index 100% rename from tools/static-assets/skel-vue/src/App.vue rename to tools/static-assets/skel-vue/imports/ui/App.vue diff --git a/tools/static-assets/skel-vue/src/components/Hello.vue b/tools/static-assets/skel-vue/imports/ui/components/Hello.vue similarity index 100% rename from tools/static-assets/skel-vue/src/components/Hello.vue rename to tools/static-assets/skel-vue/imports/ui/components/Hello.vue diff --git a/tools/static-assets/skel-vue/src/components/Info.vue b/tools/static-assets/skel-vue/imports/ui/components/Info.vue similarity index 95% rename from tools/static-assets/skel-vue/src/components/Info.vue rename to tools/static-assets/skel-vue/imports/ui/components/Info.vue index f20fc4c800..376d60562b 100644 --- a/tools/static-assets/skel-vue/src/components/Info.vue +++ b/tools/static-assets/skel-vue/imports/ui/components/Info.vue @@ -15,7 +15,7 @@