Merge branch 'master' into devel

Conflicts:
	History.md
	packages/babel-compiler/.npm/package/npm-shrinkwrap.json
	packages/babel-compiler/package.js
	packages/ecmascript/package.js
	packages/sha/package.js
	tools/upgraders.js
This commit is contained in:
Sashko Stubailo
2015-09-21 20:12:55 -04:00
277 changed files with 4588 additions and 1294 deletions

View File

@@ -1,39 +1,65 @@
## batch-plugins
Backwards-incompatible change: static assets in package.js files must
be explicitly declared with `{isAsset: true}`. See the batch-plugins merge
message for more details.
## v.NEXT
## in progress: v1.2
There are quite a lot of changes in Meteor 1.2. See the
[Wiki](https://github.com/meteor/meteor/wiki/Breaking-changes-in-Meteor-1.2) for
a shorter list of breaking changes you should be aware of when upgrading.
### Core Packages
* `meteor-platform` has been deprecated in favor of the smaller `meteor-base`,
with apps listing their other dependencies explicitly. The v1.2 upgrader
will rewrite `meteor-platform` in existing apps. `meteor-base` puts fewer
symbols in the global namepsace, so it's no longer true that all apps
have symbols like `Random` and `EJSON` in the global namespace.
* New packages: `ecmascript`, `es5-shim`, `ecmascript-collections`, `promise`,
`static-html`, `jshint`, `babel-compiler`
* No longer include the `json` package by default, which contains code for
`JSON.parse` and `JSON.stringify`. (The last browser to not support JSON
natively was Internet Explorer 7.)
### Utilities
* New `beforeSend` option to `HTTP.call` on the client allows you to directly
access the `XMLHttpRequest` object and abort the call. #4419 #3243 #3266
* Parse `application/javascript` and `application/x-javascript` HTTP replies as
JSON too. #4595
* `autoupdate` has been renamed `hot-code-push`
### Meteor Accounts
* `loginWithPassword` now matches username or email in a case insensitive manner. If there are multiple users with a username or email only differing in case, a case sensitive match is required. #550
* Login attempts are now rate-limited by default. This can be turned off
using `Accounts.removeDefaultRateLimit()`.
* `loginWithGithub` now requests `user:email` scope by default, and attempts to fetch the user's emails. If no public email has been set, we use the primary email instead. We also store the complete list of emails. #4545
* `loginWithPassword` now matches username or email in a case insensitive
manner. If there are multiple users with a username or email only differing
in case, a case sensitive match is required. #550
* `loginWithGithub` now requests `user:email` scope by default, and attempts
to fetch the user's emails. If no public email has been set, we use the
primary email instead. We also store the complete list of emails. #4545
* When an account's email address is verified, deactivate other verification
tokens. #4626
* Fix bug where blank page is shown when an expired login token is
present. #4825
* Fix `OAuth1Binding.prototype.call` when making requests to Twitter
with a large parameter set.
* Directions for setting up Google OAuth in accounts-ui have been updated to
match Google's new requirements.
### DDP
* Add `Accounts.oauth.unregisterService` method, and ensure that users can only
log in with currently registered services. #4014
* `sub.ready()` should return true inside that subscription's `onReady`
callback. #4614
* The `accounts-base` now defines reusable `AccountsClient` and
`AccountsServer` constructors, so that users can create multiple
independent instances of the `Accounts` namespace. #4233
* Create an index for `Meteor.users` on
`services.email.verificationTokens.token` (instead of
`emails.validationTokens.token`, which never was used for anything). #4482
* Remove an IE7-specific workaround from accounts-ui. #4485
### Livequery
@@ -95,15 +121,17 @@ message for more details.
iOS Simulator. As a workaround, you can `meteor run ios-device` to open the
project in Xcode and watch the output there.
## in progress: v.1.1.1
### Templates/Blaze
### Blaze
* New syntax: Handlebars sub-expressions are now supported -- as in,
`{{helper (anotherHelper arg1 arg2)}}` -- as well as new block helper forms
`#each .. in ..` and `#let x=y`. See
https://github.com/meteor/meteor/tree/devel/packages/spacebars
* Preparatory work for the yet-unreleased `react-template-helper`
package -- don't let templates use {{> React}} with siblings since
`React.render` assumes it's being rendered into an empty container
element. (This lets us throw the error when compiling templates
rather than when the app runs.)
* Add a special case for the new `react-template-helper` package -- don't let
templates use {{> React}} with siblings since `React.render` assumes it's
being rendered into an empty container element. (This lets us throw the error
when compiling templates rather than when the app runs.)
* Improve parsing of `<script>` and `<style>` tags. #3797
@@ -116,14 +144,16 @@ message for more details.
default is `Meteor.connection`, which is the connection used when calling
`Meteor.subscribe`.
* XXX Handlebars sub-expressions. https://github.com/meteor/meteor/pull/4101
* XXX `#each .. in ..` and `#let x=y` forms. https://github.com/meteor/meteor/pull/3560
* Fix external `<script>` tags in body or templates. #4415
* Fix memory leak. #4289
* Avoid recursion when materializing DOM elements, to avoid stack overflow
errors in certain browsers. #3028
* Blaze and Meteor's built-in templating are now removable using
`meteor remove blaze-html-templates`. You can add back support for static
`head` and `body` tags in `.html` files by using the `static-html` package.
### DDP
@@ -145,11 +175,17 @@ message for more details.
exceptions thrown by method stubs will be thrown instead of logged, and the
method will not be invoked on the server. #4202
* `sub.ready()` should return true inside that subscription's `onReady`
callback. #4614
* Fix method calls causing broken state when socket is reconnecting. #5104
### Isobuild
* Plugins should not process files whose names match the extension exactly (with
no extra dot). #3985
* Build plugins will no longer process files whose names match the extension
exactly (with no extra dot). If your build plugin needs to match filenames
exactly, you should use the new build plugin API in this release which
supplies a special `filenames` option. #3985
* Adding the same file twice in the same package is now an error. Previously,
this could either lead to the file being included multiple times, or to a
@@ -161,14 +197,56 @@ message for more details.
* Ignore `node_modules` directories in apps instead of processing them as Meteor
source code. #4457 #4452
### Livequery
* Backwards-incompatible change for package authors: Static assets in package.js files must now be
explicitly declared by using `addAssets` instead of `addFiles`. Previously,
any file that didn't have a source handler was automatically registered as a
server-side asset. The `isAsset` option to `addFiles` is also deprecated in
favor of `addAssets`.
* Built files are now always annotated with line number comments, to improve the
debugging experience in browsers that don't support source maps.
* There is a completely new API for defining build plugins that cache their
output. There are now special APIs for defining linters and minifiers in
addition to compilers. The core Meteor packages for `less`, `coffee`, `stylus`
and `html` files have been updated to use this new API. Read more on the
[Wiki page](https://github.com/meteor/meteor/wiki/Build-Plugins-API).
### CSS
* LESS and Stylus now support cross-package imports.
* CSS concatenation and minification is delegated to the `standard-minifiers`
package, which is present by default (and added to existing apps by the v1.2
upgrader).
* CSS output is now split into multiple stylesheets to avoid hitting limits on
rules per stylesheet in certain versions of Internet Explorer. #1876
### Mongo
* The oplog observe driver now properly updates queries when you drop a
database. #3847
* MongoID logic has been moved out of `minimongo` into a new package called
`mongo-id`.
* Fix Mongo upserts with dotted keys in selector. #4522
### `meteor` command-line tool
* You can now create three new example apps with the command line tool. These
are the apps from the official tutorials at http://meteor.com/tutorials, which
demonstrate building the same app with Blaze, Angular, and React. Try these
apps with:
```sh
meteor create --example simple-todos
meteor create --example simple-todos-react
meteor create --example simple-todos-angular
```
* `meteor shell` no longer crashes when piped from another command.
* Avoid a race condition in `meteor --test` and work with newer versions of the
@@ -199,20 +277,7 @@ message for more details.
* Fix inability to run `mongod` due to lack of locale configuration on some
platforms, and improve error message if the failure still occurs. #4019
### Meteor Accounts
* Add `Accounts.oauth.unregisterService` method, and ensure that users can only
log in with currently registered services. #4014
* The `accounts-base` now defines reusable `AccountsClient` and
`AccountsServer` constructors, so that users can create multiple
independent instances of the `Accounts` namespace. #4233
* Create an index for `Meteor.users` on
`services.email.verificationTokens.token` (instead of
`emails.validationTokens.token`, which never was used for anything). #4482
* Remove an IE7-specific workaround from accounts-ui. #4485
* New `meteor lint` command.
### Minimongo
@@ -231,14 +296,20 @@ message for more details.
* New `Tracker.Computation#onStop` method. #3915
* `ReactiveDict` now has two new methods, `clear` and `all`. `clear` resets
* `ReactiveDict` has two new methods, `clear` and `all`. `clear` resets
the dictionary as if no items had been added, meaning all calls to `get` will
return `underfined`. `all` converts the dictionary into a regular JavaScript
return `undefined`. `all` converts the dictionary into a regular JavaScript
object with a snapshot of the keys and values. Inside an autorun, `all`
registers a dependency on any changes to the dictionary.
registers a dependency on any changes to the dictionary. #3135
### Utilities
* New `beforeSend` option to `HTTP.call` on the client allows you to directly
access the `XMLHttpRequest` object and abort the call. #4419 #3243 #3266
* Parse `application/javascript` and `application/x-javascript` HTTP replies as
JSON too. #4595
* `Match.test` from the `check` package now properly compares boolean literals,
just like it does with Numbers and Strings. This applies to the `check`
function as well.
@@ -250,10 +321,11 @@ message for more details.
* Expose `Spiderable.requestTimeoutMs` from `spiderable` package to
allow apps to set the timeout for running phantomjs.
### Other bug fixes and improvements
* The `spiderable` package now reports the URL it's trying to fetch on failure.
### Other bug fixes and improvements
* Upgraded dependencies:
- Node: 0.10.40 (from 0.10.36)
@@ -264,10 +336,26 @@ message for more details.
displayed on Google login.
* Upgraded `coffeescript` package to depend on NPM packages
coffeescript@1.9.2 and source-map@0.4.2.
coffeescript@1.9.2 and source-map@0.4.2. #4302
* Upgraded `fastclick` to 1.0.6 to fix an issue in iOS Safari. #4393
* Fix `Error: Can't render headers after they are sent to the client`. #4253 #4750
* `Meteor.settings.public` is always available on client and server,
and modifications made on the server (for example, during app initialization)
affect the value seen by connecting clients. #4704
### Windows
* Increase the buffer size for `netstat` when looking for running Mongo servers.
#4125
* The Windows installer now always fetches the latest available version of
Meteor at runtime, so that it doesn't need to be recompiled for every release.
* Fix crash in `meteor mongo` on Windows. #4711
## v1.1.0.3, 2015-Aug-03

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -1 +0,0 @@

View File

@@ -3,7 +3,6 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-platform
standard-minifiers
jquery
underscore
@@ -14,3 +13,15 @@ reload-safetybelt
simple:markdown-templating
simple:highlight.js
less
meteor-base
mobile-experience
mongo
blaze-html-templates
session
tracker
logging
reload
random
ejson
spacebars
check

View File

@@ -1 +1 @@
METEOR@1.1.0.3
METEOR@1.2

View File

@@ -1,55 +1,71 @@
appcache@1.0.4
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
less@1.0.14
livedata@1.0.13
logging@1.0.7
markdown@1.0.4
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
observe-sequence@1.0.6
ordered-dict@1.0.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
reload-safetybelt@1.0.3
retry@1.0.3
routepolicy@1.0.5
session@1.1.0
showdown@1.0.4
simple:highlight.js@1.0.9
simple:markdown-templating@1.2.6
spacebars@1.0.6
spacebars-compiler@1.0.6
spiderable@1.0.7
standard-app-packages@1.0.5
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
appcache@1.0.5
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
jquery@1.11.4
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
logging@1.0.8
markdown@1.0.5
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
reload-safetybelt@1.0.4
retry@1.0.4
routepolicy@1.0.6
session@1.1.1
showdown@1.0.5
simple:highlight.js@1.1.0
simple:markdown-templating@1.2.7
spacebars@1.0.7
spacebars-compiler@1.0.7
spiderable@1.0.9
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -9,10 +9,52 @@ DocsData = {
"scope": "global",
"summary": "The namespace for all server-side accounts-related methods."
},
"Accounts.addEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 847,
"locus": "Server",
"longname": "Accounts.addEmail",
"memberof": "Accounts",
"name": "addEmail",
"options": [],
"params": [
{
"description": "<p>The ID of the user to update.</p>",
"name": "userId",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>A new email address for the user.</p>",
"name": "newEmail",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>Optional - whether the new email address should\nbe marked as verified. Defaults to false.</p>",
"name": "verified",
"optional": true,
"type": {
"names": [
"Boolean"
]
}
}
],
"scope": "static",
"summary": "Add an email address for a user. Use this instead of directly\nupdating the database. The operation will fail if there is a different user\nwith an email only differing in case. If the specified user has an existing\nemail only differing in case however, we replace it."
},
"Accounts.changePassword": {
"filepath": "accounts-password/password_client.js",
"kind": "function",
"lineno": 150,
"lineno": 148,
"locus": "Client",
"longname": "Accounts.changePassword",
"memberof": "Accounts",
@@ -131,10 +173,76 @@ DocsData = {
"scope": "static",
"summary": "Options to customize emails sent from the Accounts system."
},
"Accounts.findUserByEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 138,
"locus": "Server",
"longname": "Accounts.findUserByEmail",
"memberof": "Accounts",
"name": "findUserByEmail",
"options": [],
"params": [
{
"description": "<p>The email address to look for</p>",
"name": "email",
"type": {
"names": [
"String"
]
}
}
],
"returns": [
{
"description": "<p>A user if found, else null</p>",
"type": {
"names": [
"Object"
]
}
}
],
"scope": "static",
"summary": "Finds the user with the specified email.\nFirst tries to match email case sensitively; if that fails, it\ntries case insensitively; but if more than one user matches the case\ninsensitive search, it returns null."
},
"Accounts.findUserByUsername": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 123,
"locus": "Server",
"longname": "Accounts.findUserByUsername",
"memberof": "Accounts",
"name": "findUserByUsername",
"options": [],
"params": [
{
"description": "<p>The username to look for</p>",
"name": "username",
"type": {
"names": [
"String"
]
}
}
],
"returns": [
{
"description": "<p>A user if found, else null</p>",
"type": {
"names": [
"Object"
]
}
}
],
"scope": "static",
"summary": "Finds the user with the specified username.\nFirst tries to match username case sensitively; if that fails, it\ntries case insensitively; but if more than one user matches the case\ninsensitive search, it returns null."
},
"Accounts.forgotPassword": {
"filepath": "accounts-password/password_client.js",
"kind": "function",
"lineno": 212,
"lineno": 210,
"locus": "Client",
"longname": "Accounts.forgotPassword",
"memberof": "Accounts",
@@ -242,10 +350,42 @@ DocsData = {
"scope": "static",
"summary": "Register a function to call when a reset password link is clicked\nin an email sent by\n[`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail).\nThis function should be called in top-level code, not inside\n`Meteor.startup()`."
},
"Accounts.removeEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 930,
"locus": "Server",
"longname": "Accounts.removeEmail",
"memberof": "Accounts",
"name": "removeEmail",
"options": [],
"params": [
{
"description": "<p>The ID of the user to update.</p>",
"name": "userId",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>The email address to remove.</p>",
"name": "email",
"type": {
"names": [
"String"
]
}
}
],
"scope": "static",
"summary": "Remove an email address for a user. Use this instead of updating\nthe database directly."
},
"Accounts.resetPassword": {
"filepath": "accounts-password/password_client.js",
"kind": "function",
"lineno": 232,
"lineno": 230,
"locus": "Client",
"longname": "Accounts.resetPassword",
"memberof": "Accounts",
@@ -287,7 +427,7 @@ DocsData = {
"Accounts.sendEnrollmentEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 509,
"lineno": 584,
"locus": "Server",
"longname": "Accounts.sendEnrollmentEmail",
"memberof": "Accounts",
@@ -320,7 +460,7 @@ DocsData = {
"Accounts.sendResetPasswordEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 444,
"lineno": 519,
"locus": "Server",
"longname": "Accounts.sendResetPasswordEmail",
"memberof": "Accounts",
@@ -353,7 +493,7 @@ DocsData = {
"Accounts.sendVerificationEmail": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 648,
"lineno": 723,
"locus": "Server",
"longname": "Accounts.sendVerificationEmail",
"memberof": "Accounts",
@@ -386,7 +526,7 @@ DocsData = {
"Accounts.setPassword": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 396,
"lineno": 471,
"locus": "Server",
"longname": "Accounts.setPassword",
"memberof": "Accounts",
@@ -434,6 +574,38 @@ DocsData = {
"scope": "static",
"summary": "Forcibly change the password for a user."
},
"Accounts.setUsername": {
"filepath": "accounts-password/password_server.js",
"kind": "function",
"lineno": 372,
"locus": "Server",
"longname": "Accounts.setUsername",
"memberof": "Accounts",
"name": "setUsername",
"options": [],
"params": [
{
"description": "<p>The ID of the user to update.</p>",
"name": "userId",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>A new username for the user.</p>",
"name": "newUsername",
"type": {
"names": [
"String"
]
}
}
],
"scope": "static",
"summary": "Change a user's username. Use this instead of updating the\ndatabase directly. The operation will fail if there is an existing user\nwith a username only differing in case."
},
"Accounts.ui": {
"filepath": "accounts-ui-unstyled/accounts_ui.js",
"kind": "namespace",
@@ -506,7 +678,7 @@ DocsData = {
"Accounts.verifyEmail": {
"filepath": "accounts-password/password_client.js",
"kind": "function",
"lineno": 259,
"lineno": 257,
"locus": "Client",
"longname": "Accounts.verifyEmail",
"memberof": "Accounts",
@@ -1260,7 +1432,7 @@ DocsData = {
"params": [
{
"description": "<p>The identifier of the plugin you want to\nconfigure.</p>",
"name": "pluginName",
"name": "id",
"type": {
"names": [
"String"
@@ -1278,7 +1450,7 @@ DocsData = {
}
],
"scope": "static",
"summary": "Set the build-time configuration for a Phonegap plugin."
"summary": "Set the build-time configuration for a Cordova plugin."
},
"App.icons": {
"kind": "function",
@@ -1307,7 +1479,7 @@ DocsData = {
"name": "info",
"options": [
{
"description": "<p>Each of the options correspond to a key in the app's core configuration\nas described in the <a href=\"http://docs.phonegap.com/en/3.5.0/config_ref_index.md.html#The%20config.xml%20File_core_configuration_elements\">PhoneGap documentation</a>.</p>",
"description": "<p>Each of the options correspond to a key in the app's core configuration\nas described in the <a href=\"http://cordova.apache.org/docs/en/5.1.1/config_ref_index.md.html#The%20config.xml%20File_core_configuration_elements\">Cordova documentation</a>.</p>",
"name": "id, version, name, description, author, email, website",
"optional": true,
"type": {
@@ -1358,7 +1530,7 @@ DocsData = {
"options": [],
"params": [
{
"description": "<p>A preference name supported by Phonegap's\n<code>config.xml</code>.</p>",
"description": "<p>A preference name supported by Cordova's\n<code>config.xml</code>.</p>",
"name": "name",
"type": {
"names": [
@@ -1374,10 +1546,20 @@ DocsData = {
"String"
]
}
},
{
"description": "<p>Optional. A platform name (either <code>ios</code> or <code>android</code>) to add a platform-specific preference.</p>",
"name": "platform",
"optional": true,
"type": {
"names": [
"String"
]
}
}
],
"scope": "static",
"summary": "Add a preference for your build as described in the\n[PhoneGap documentation](http://docs.phonegap.com/en/3.5.0/config_ref_index.md.html#The%20config.xml%20File_global_preferences)."
"summary": "Add a preference for your build as described in the\n[Cordova documentation](http://cordova.apache.org/docs/en/5.1.1/config_ref_index.md.html#The%20config.xml%20File_global_preferences)."
},
"Assets": {
"kind": "namespace",
@@ -2727,7 +2909,7 @@ DocsData = {
"DDP.connect": {
"filepath": "ddp-client/livedata_connection.js",
"kind": "function",
"lineno": 1627,
"lineno": 1641,
"locus": "Anywhere",
"longname": "DDP.connect",
"memberof": "DDP",
@@ -3540,7 +3722,7 @@ DocsData = {
"HTTP.del": {
"filepath": "http/httpcall_common.js",
"kind": "function",
"lineno": 78,
"lineno": 82,
"locus": "Anywhere",
"longname": "HTTP.del",
"memberof": "HTTP",
@@ -3583,7 +3765,7 @@ DocsData = {
"HTTP.get": {
"filepath": "http/httpcall_common.js",
"kind": "function",
"lineno": 45,
"lineno": 49,
"locus": "Anywhere",
"longname": "HTTP.get",
"memberof": "HTTP",
@@ -3626,7 +3808,7 @@ DocsData = {
"HTTP.post": {
"filepath": "http/httpcall_common.js",
"kind": "function",
"lineno": 56,
"lineno": 60,
"locus": "Anywhere",
"longname": "HTTP.post",
"memberof": "HTTP",
@@ -3669,7 +3851,7 @@ DocsData = {
"HTTP.put": {
"filepath": "http/httpcall_common.js",
"kind": "function",
"lineno": 67,
"lineno": 71,
"locus": "Anywhere",
"longname": "HTTP.put",
"memberof": "HTTP",
@@ -4729,7 +4911,7 @@ DocsData = {
"Meteor.logout": {
"filepath": "accounts-base/accounts_client.js",
"kind": "function",
"lineno": 332,
"lineno": 334,
"locus": "Client",
"longname": "Meteor.logout",
"memberof": "Meteor",
@@ -4753,7 +4935,7 @@ DocsData = {
"Meteor.logoutOtherClients": {
"filepath": "accounts-base/accounts_client.js",
"kind": "function",
"lineno": 341,
"lineno": 343,
"locus": "Client",
"longname": "Meteor.logoutOtherClients",
"memberof": "Meteor",
@@ -4954,7 +5136,7 @@ DocsData = {
"memberof": "Meteor",
"name": "settings",
"scope": "static",
"summary": "`Meteor.settings` contains deployment-specific configuration options. You can initialize settings by passing the `--settings` option (which takes the name of a file containing JSON data) to `meteor run` or `meteor deploy`. When running your server directly (e.g. from a bundle), you instead specify settings by putting the JSON directly into the `METEOR_SETTINGS` environment variable. If you don't provide any settings, `Meteor.settings` will be an empty object. If the settings object contains a key named `public`, then `Meteor.settings.public` will be available on the client as well as the server. All other properties of `Meteor.settings` are only defined on the server.",
"summary": "`Meteor.settings` contains deployment-specific configuration options. You can initialize settings by passing the `--settings` option (which takes the name of a file containing JSON data) to `meteor run` or `meteor deploy`. When running your server directly (e.g. from a bundle), you instead specify settings by putting the JSON directly into the `METEOR_SETTINGS` environment variable. If the settings object contains a key named `public`, then `Meteor.settings.public` will be available on the client as well as the server. All other properties of `Meteor.settings` are only defined on the server. You can rely on `Meteor.settings` and `Meteor.settings.public` being defined objects (not undefined) on both client and server even if there are no settings specified. Changes to `Meteor.settings.public` at runtime will be picked up by new client connections.",
"type": {
"names": [
"Object"
@@ -5189,7 +5371,7 @@ DocsData = {
"Mongo.Collection#allow": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 782,
"lineno": 787,
"locus": "Server",
"longname": "Mongo.Collection#allow",
"memberof": "Mongo.Collection",
@@ -5239,7 +5421,7 @@ DocsData = {
"Mongo.Collection#deny": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 794,
"lineno": 799,
"locus": "Server",
"longname": "Mongo.Collection#deny",
"memberof": "Mongo.Collection",
@@ -5289,7 +5471,7 @@ DocsData = {
"Mongo.Collection#find": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 252,
"lineno": 257,
"locus": "Anywhere",
"longname": "Mongo.Collection#find",
"memberof": "Mongo.Collection",
@@ -5386,7 +5568,7 @@ DocsData = {
"Mongo.Collection#findOne": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 278,
"lineno": 283,
"locus": "Anywhere",
"longname": "Mongo.Collection#findOne",
"memberof": "Mongo.Collection",
@@ -5474,7 +5656,7 @@ DocsData = {
"Mongo.Collection#insert": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 422,
"lineno": 427,
"locus": "Anywhere",
"longname": "Mongo.Collection#insert",
"memberof": "Mongo.Collection",
@@ -5507,7 +5689,7 @@ DocsData = {
"Mongo.Collection#rawCollection": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 651,
"lineno": 656,
"locus": "Server",
"longname": "Mongo.Collection#rawCollection",
"memberof": "Mongo.Collection",
@@ -5520,7 +5702,7 @@ DocsData = {
"Mongo.Collection#rawDatabase": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 663,
"lineno": 668,
"locus": "Server",
"longname": "Mongo.Collection#rawDatabase",
"memberof": "Mongo.Collection",
@@ -5533,7 +5715,7 @@ DocsData = {
"Mongo.Collection#remove": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 446,
"lineno": 451,
"locus": "Anywhere",
"longname": "Mongo.Collection#remove",
"memberof": "Mongo.Collection",
@@ -5566,7 +5748,7 @@ DocsData = {
"Mongo.Collection#update": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 432,
"lineno": 437,
"locus": "Anywhere",
"longname": "Mongo.Collection#update",
"memberof": "Mongo.Collection",
@@ -5636,7 +5818,7 @@ DocsData = {
"Mongo.Collection#upsert": {
"filepath": "mongo/collection.js",
"kind": "function",
"lineno": 608,
"lineno": 613,
"locus": "Anywhere",
"longname": "Mongo.Collection#upsert",
"memberof": "Mongo.Collection",
@@ -5698,7 +5880,7 @@ DocsData = {
"filepath": "mongo/collection.js",
"instancename": "cursor",
"kind": "class",
"lineno": 685,
"lineno": 690,
"longname": "Mongo.Cursor",
"memberof": "Mongo",
"name": "Cursor",
@@ -5866,7 +6048,7 @@ DocsData = {
"Mongo.ObjectID": {
"filepath": "mongo/collection.js",
"kind": "class",
"lineno": 678,
"lineno": 683,
"locus": "Anywhere",
"longname": "Mongo.ObjectID",
"memberof": "Mongo",
@@ -5876,6 +6058,7 @@ DocsData = {
{
"description": "<p>Optional. The 24-character hexadecimal contents of the ObjectID to create</p>",
"name": "hexString",
"optional": true,
"type": {
"names": [
"String"
@@ -6138,17 +6321,17 @@ DocsData = {
"scope": "global",
"summary": "Type of the API object passed into the `Package.onUse` function."
},
"PackageAPI#addFiles": {
"PackageAPI#addAssets": {
"kind": "function",
"locus": "package.js",
"longname": "PackageAPI#addFiles",
"longname": "PackageAPI#addAssets",
"memberof": "PackageAPI",
"name": "addFiles",
"name": "addAssets",
"options": [],
"params": [
{
"description": "<p>Name of the source file, or array of\nstrings of source file names.</p>",
"name": "filename",
"description": "<p>Paths to the asset files.</p>",
"name": "filenames",
"type": {
"names": [
"String",
@@ -6157,7 +6340,50 @@ DocsData = {
}
},
{
"description": "<p>If you only want to export the file\non the server (or the client), you can pass in the second argument\n(e.g., 'server', 'client', 'web.browser', 'web.cordova') to specify\nwhat architecture the file is used with. You can specify multiple\narchitectures by passing in an array, for example <code>['web.cordova', 'os.linux']</code>.</p>",
"description": "<p>Specify where this asset should be\navailable (e.g., 'server', 'client', 'web.browser', 'web.cordova'). You can\nspecify multiple architectures by passing in an array, for example\n<code>['web.cordova', 'os.linux']</code>.</p>",
"name": "architecture",
"type": {
"names": [
"String",
"Array.<String>"
]
}
}
],
"scope": "instance",
"summary": "Specify asset files for your package. They can be accessed via\nthe [Assets API](#assets) from the server, or at the URL\n`/packages/username_package-name/file-name` from the client, depending on the\narchitecture passed."
},
"PackageAPI#addFiles": {
"kind": "function",
"locus": "package.js",
"longname": "PackageAPI#addFiles",
"memberof": "PackageAPI",
"name": "addFiles",
"options": [
{
"description": "<p>If this file is JavaScript code or will\nbe compiled into JavaScript code by a build plugin, don't wrap the\nresulting file in a closure. Has the same effect as putting a file into the\n<code>client/compatibility</code> directory in an app.</p>",
"name": "bare",
"optional": true,
"type": {
"names": [
"Boolean"
]
}
}
],
"params": [
{
"description": "<p>Paths to the source files.</p>",
"name": "filenames",
"type": {
"names": [
"String",
"Array.<String>"
]
}
},
{
"description": "<p>If you only want to use the file\non the server (or the client), you can pass this argument\n(e.g., 'server', 'client', 'web.browser', 'web.cordova') to specify\nwhat architecture the file is used with. You can specify multiple\narchitectures by passing in an array, for example\n<code>['web.cordova', 'os.linux']</code>. By default, the file will be loaded on both\nserver and client.</p>",
"name": "architecture",
"optional": true,
"type": {
@@ -6168,8 +6394,8 @@ DocsData = {
}
},
{
"description": "<p>Options that will be passed to build\nplugins. For example, for JavaScript files, you can pass <code>{bare: true}</code>\nto not wrap the individual file in its own closure. To add a static asset,\npass <code>{isAsset: true}</code>; use the <code>architecture</code> parameter to determine\nif this is a client-side asset served by the HTTP server or a server-side\nasset accessible to the <code>Assets</code> APIs.</p>",
"name": "fileOptions",
"description": "<p>Options that will be passed to build\nplugins.</p>",
"name": "options",
"optional": true,
"type": {
"names": [
@@ -6179,7 +6405,7 @@ DocsData = {
}
],
"scope": "instance",
"summary": "Specify the source code for your package."
"summary": "Specify source code files for your package."
},
"PackageAPI#export": {
"kind": "function",
@@ -6230,7 +6456,7 @@ DocsData = {
}
],
"scope": "instance",
"summary": "Export package-level variables in your package. The specified\nvariables (declared without `var` in the source code) will be available\nto packages that use this package."
"summary": "Export package-level variables in your package. The specified\nvariables (declared without `var` in the source code) will be available\nto packages that use your package. If your package sets the `debugOnly`\nor `prodOnly` options to `true` when it calls `Package.describe()`, then\npackages that use your package will need to use \n`Package[\"package-name\"].ExportedVariableName` to access the value of an\nexported variable."
},
"PackageAPI#imply": {
"kind": "function",
@@ -7671,12 +7897,211 @@ DocsData = {
"filepath": "accounts-base/accounts_client.js",
"ishelper": "true",
"kind": "member",
"lineno": 408,
"lineno": 410,
"longname": "currentUser",
"name": "currentUser",
"scope": "global",
"summary": "Calls [Meteor.user()](#meteor_user). Use `{{#if currentUser}}` to check whether the user is logged in."
},
"execFileAsync": {
"kind": "function",
"longname": "execFileAsync",
"name": "execFileAsync",
"options": [
{
"description": "<p>Current working directory of the child process</p>",
"name": "cwd",
"optional": true,
"type": {
"names": [
"Object"
]
}
},
{
"description": "<p>Environment key-value pairs</p>",
"name": "env",
"optional": true,
"type": {
"names": [
"Object"
]
}
},
{
"description": "<p>Child's stdio configuration.\n(Default: 'pipe') Specifying anything else than 'pipe' will disallow\ncapture.</p>",
"name": "stdio",
"optional": true,
"type": {
"names": [
"Array",
"String"
]
}
},
{
"description": "<p>If specified, instead of capturing\nthe output, the child process stdout will be piped to the destination stream.</p>",
"name": "destination",
"optional": true,
"type": {
"names": [
"Writable"
]
}
},
{
"description": "<p>Whether to wait for the child process\nstreams to close or to resolve the promise when the child process exits.</p>",
"name": "waitForClose",
"optional": true,
"type": {
"names": [
"String"
]
}
}
],
"params": [
{
"description": "<p>The command to run</p>",
"name": "command",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>List of string arguments</p>",
"name": "args",
"optional": true,
"type": {
"names": [
"Array"
]
}
},
{
"name": "options",
"optional": true,
"type": {
"names": [
"Object"
]
}
}
],
"returns": [
{
"type": {
"names": [
"Promise.<String>"
]
}
}
],
"scope": "global",
"summary": "Executes a command asynchronously, returning a promise that will\neither be resolved to the captured stdout output or be rejected with an\nerror containing the stderr output as part of the message. In addition,\nthe error will contain fields pid, stderr, stdout, status and signal."
},
"execFileSync": {
"kind": "function",
"longname": "execFileSync",
"name": "execFileSync",
"options": [
{
"description": "<p>Current working directory of the child process</p>",
"name": "cwd",
"optional": true,
"type": {
"names": [
"Object"
]
}
},
{
"description": "<p>Environment key-value pairs</p>",
"name": "env",
"optional": true,
"type": {
"names": [
"Object"
]
}
},
{
"description": "<p>Child's stdio configuration.\n(Default: 'pipe') Specifying anything else than 'pipe' will disallow\ncapture.</p>",
"name": "stdio",
"optional": true,
"type": {
"names": [
"Array",
"String"
]
}
},
{
"description": "<p>If specified, instead of capturing\nthe output, the child process stdout will be piped to the destination stream.</p>",
"name": "destination",
"optional": true,
"type": {
"names": [
"Writable"
]
}
},
{
"description": "<p>Whether to wait for the child process\nstreams to close or to resolve the promise when the child process exits.</p>",
"name": "waitForClose",
"optional": true,
"type": {
"names": [
"String"
]
}
}
],
"params": [
{
"description": "<p>The command to run</p>",
"name": "command",
"type": {
"names": [
"String"
]
}
},
{
"description": "<p>List of string arguments</p>",
"name": "args",
"optional": true,
"type": {
"names": [
"Array"
]
}
},
{
"name": "options",
"optional": true,
"type": {
"names": [
"Object"
]
}
}
],
"returns": [
{
"description": "<p>The stdout from the command</p>",
"type": {
"names": [
"String"
]
}
}
],
"scope": "global",
"summary": "Executes a command synchronously, returning either the captured\nstdout output or throwing an error containing the stderr output as part of\nthe message. In addition, the error will contain fields pid, stderr, stdout,\nstatus and signal."
},
"getExtension": {
"kind": "function",
"longname": "getExtension",
@@ -7699,7 +8124,7 @@ DocsData = {
"filepath": "accounts-base/accounts_client.js",
"ishelper": "true",
"kind": "member",
"lineno": 418,
"lineno": 420,
"longname": "loggingIn",
"name": "loggingIn",
"scope": "global",

View File

@@ -40,6 +40,8 @@ App.launchScreens({
// Set PhoneGap/Cordova preferences
App.setPreference('BackgroundColor', '0xff0000ff');
App.setPreference('HideKeyboardFormAccessoryBar', true);
App.setPreference('Orientation', 'default');
App.setPreference('Orientation', 'all', 'ios');
// Pass preferences for a particular PhoneGap/Cordova plugin
App.configurePlugin('com.phonegap.plugins.facebookconnect', {

View File

@@ -88,6 +88,7 @@ package is exported to.
{{> autoApiBox "PackageAPI#imply" }}
{{> autoApiBox "PackageAPI#export" }}
{{> autoApiBox "PackageAPI#addFiles" }}
{{> autoApiBox "PackageAPI#addAssets" }}
<h3 id="packagetests"><span>Unit Tests</span></h3>

View File

@@ -31,9 +31,10 @@ id.
On the client, you must pass `password` and at least one of `username` or
`email` &mdash; enough information for the user to be able to log in again
later. If there are existing users with a username or email only differing in case, `createUser` will fail. On the server, you do not need to specify `password`, but the user will
not be able to log in until it has a password (eg, set with
[`Accounts.setPassword`](#accounts_setpassword)).
later. If there are existing users with a username or email only differing in
case, `createUser` will fail. On the server, you do not need to specify
`password`, but the user will not be able to log in until it has a password (eg,
set with [`Accounts.setPassword`](#accounts_setpassword)).
To create an account without a password on the server and still let the
user pick their own password, call `createUser` with the `email` option
@@ -47,6 +48,35 @@ override this behavior, use [`Accounts.onCreateUser`](#accounts_oncreateuser).
This function is only used for creating users with passwords. The external
service login flows do not use this function.
### Managing usernames and emails
Instead of modifying documents in the [`Meteor.users`](#meteor_users) collection
directly, use these convenience functions which correctly check for case
insensitive duplicates before updates.
{{> autoApiBox "Accounts.setUsername"}}
{{> autoApiBox "Accounts.addEmail"}}
By default, an email address is added with `{ verified: false }`. Use
[`Accounts.sendVerificationEmail`](#Accounts-sendVerificationEmail) to send an
email with a link the user can use verify their email address.
{{> autoApiBox "Accounts.removeEmail"}}
{{> autoApiBox "Accounts.verifyEmail"}}
This function accepts tokens passed into the callback registered with
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink).
{{> autoApiBox "Accounts.findUserByUsername"}}
{{> autoApiBox "Accounts.findUserByEmail"}}
### Managing passwords
Use the below functions to initiate password changes or resets from the server
or the client.
{{> autoApiBox "Accounts.changePassword"}}
@@ -70,10 +100,9 @@ This function accepts tokens passed into the callbacks registered with
{{> autoApiBox "Accounts.setPassword"}}
{{> autoApiBox "Accounts.verifyEmail"}}
This function accepts tokens passed into the callback registered with
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink).
<h3 id="sending-emails"><span>Sending emails</span></h3>
{{> autoApiBox "Accounts.sendResetPasswordEmail"}}

View File

@@ -21,11 +21,6 @@ advanced facilities such as `Tracker.Dependency` and `onInvalidate`
callbacks are intended primarily for package authors implementing new
reactive data sources.
To learn more about how Tracker works and to explore advanced ways to use it,
visit the <a href="http://manual.meteor.com/#tracker"> Tracker</a> chapter in the
<a href="http://manual.meteor.com/">Meteor Manual</a>, which describes it in
complete detail.
{{> autoApiBox "Tracker.autorun" }}
`Tracker.autorun` allows you to run a function that depends on reactive data

View File

@@ -157,11 +157,20 @@ var toc = [
{name: "Passwords", id: "accounts_passwords"}, [
"Accounts.createUser",
{type: "spacer"},
{name: "Accounts.setUsername", id: "Accounts-setUsername"},
{name: "Accounts.addEmail", id: "Accounts-addEmail"},
{name: "Accounts.removeEmail", id: "Accounts-removeEmail"},
{name: "Accounts.verifyEmail", id: "accounts_verifyemail"},
{name: "Accounts.findUserByUsername", id: "Accounts-findUserByUsername"},
{name: "Accounts.findUserByEmail", id: "Accounts-findUserByEmail"},
{type: "spacer"},
"Accounts.changePassword",
"Accounts.forgotPassword",
"Accounts.resetPassword",
"Accounts.setPassword",
"Accounts.verifyEmail",
{type: "spacer"},
"Accounts.sendResetPasswordEmail",
@@ -313,7 +322,8 @@ var toc = [
{name: "api.use", id: "pack_use"},
{name: "api.imply", id: "pack_api_imply"},
{name: "api.export", id: "pack_export"},
{name: "api.addFiles", id: "pack_addFiles"}
{name: "api.addFiles", id: "pack_addFiles"},
{name: "api.addAssets", id: "PackageAPI-addAssets"}
],
{name: "Package.onTest", id: "packagetests"},
{name: "Npm.depends", id: "Npm-depends"},

View File

@@ -1,4 +1,4 @@
release = Meteor.release ? "1.1.0.3" : "(checkout)";
release = Meteor.release ? "1.2" : "(checkout)";
Template.registerHelper("release", release);

View File

@@ -4,6 +4,27 @@
<meta name="Description"
content="Meteor is an open-source JavaScript platform for building top-quality web apps in a fraction of the time, whether you're an expert developer or just getting started."/>
<link rel="icon" href="/favicon.png" type="image/png" />
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-M2CMWR"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-M2CMWR');</script>
<!-- End Google Tag Manager -->
<!-- Start of Async HubSpot Analytics Code -->
<script type="text/javascript">
(function(d,s,i,r) {
if (d.getElementById(i)){return;}
var n=d.createElement(s),e=d.getElementsByTagName(s)[0];
n.id=i;n.src='//js.hs-analytics.net/analytics/'+(Math.ceil(new Date()/r)*r)+'/520701.js';
e.parentNode.insertBefore(n, e);
})(document,"script","hs-analytics",300000);
</script>
<!-- End of Async HubSpot Analytics Code -->
</head>
<body>

View File

@@ -1,18 +1,23 @@
[
"Accounts",
"Accounts",
"Accounts.addEmail",
"Accounts.changePassword",
"Accounts.createUser",
"Accounts.emailTemplates",
"Accounts.findUserByEmail",
"Accounts.findUserByUsername",
"Accounts.forgotPassword",
"Accounts.onEmailVerificationLink",
"Accounts.onEnrollmentLink",
"Accounts.onResetPasswordLink",
"Accounts.removeEmail",
"Accounts.resetPassword",
"Accounts.sendEnrollmentEmail",
"Accounts.sendResetPasswordEmail",
"Accounts.sendVerificationEmail",
"Accounts.setPassword",
"Accounts.setUsername",
"Accounts.ui",
"Accounts.ui.config",
"Accounts.verifyEmail",
@@ -210,6 +215,7 @@
"Package.onUse",
"Package.registerBuildPlugin",
"PackageAPI",
"PackageAPI#addAssets",
"PackageAPI#addFiles",
"PackageAPI#export",
"PackageAPI#imply",
@@ -275,6 +281,8 @@
"Tracker.onInvalidate",
"check",
"currentUser",
"execFileAsync",
"execFileSync",
"getExtension",
"loggingIn"
]

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -1 +1 @@
METEOR@1.1.0.3
METEOR@1.2

View File

@@ -1,48 +1,59 @@
autopublish@1.0.3
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
insecure@1.0.3
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
livedata@1.0.13
logging@1.0.7
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
observe-sequence@1.0.6
ordered-dict@1.0.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
session@1.1.0
spacebars@1.0.6
spacebars-compiler@1.0.6
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
jquery@1.11.4
livedata@1.0.14
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mongo@1.1.1
mongo-id@1.0.1
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
session@1.1.1
spacebars@1.0.7
spacebars-compiler@1.0.7
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -8,3 +8,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -1 +1 @@
METEOR@1.1.0.3
METEOR@1.2

View File

@@ -1,48 +1,61 @@
autopublish@1.0.3
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
insecure@1.0.3
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
livedata@1.0.13
logging@1.0.7
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
observe-sequence@1.0.6
ordered-dict@1.0.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
session@1.1.0
spacebars@1.0.6
spacebars-compiler@1.0.6
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
autopublish@1.0.4
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
insecure@1.0.4
jquery@1.11.4
livedata@1.0.14
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mongo@1.1.1
mongo-id@1.0.1
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
session@1.1.1
spacebars@1.0.7
spacebars-compiler@1.0.7
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -5,7 +5,6 @@
# but you can also edit it by hand.
# Packages from the release:
meteor-platform
standard-minifiers
less
email
@@ -24,3 +23,16 @@ percolate:velocityjs
percolate:wireframing
mdg:camera
mdg:geolocation
meteor-base
mobile-experience
mongo
blaze-html-templates
session
jquery
tracker
logging
reload
random
ejson
spacebars
check

View File

@@ -1 +1 @@
METEOR@1.1.0.3
METEOR@1.2

View File

@@ -1,67 +1,86 @@
accounts-base@1.2.0
accounts-oauth@1.1.5
accounts-twitter@1.0.4
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
coffeescript@1.0.6
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
email@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
accounts-base@1.2.1
accounts-oauth@1.1.6
accounts-twitter@1.0.5
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
coffeescript@1.0.8
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
iron:core@0.3.4
iron:dynamic-template@0.4.1
iron:layout@0.4.1
iron:router@0.9.4
jquery@1.11.3_2
jquery-waypoints@1.0.3
json@1.0.3
launch-screen@1.0.2
less@1.0.14
livedata@1.0.13
localstorage@1.0.3
logging@1.0.7
mdg:camera@1.1.4
mdg:geolocation@1.0.2
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
oauth@1.1.4
oauth1@1.1.4
observe-sequence@1.0.6
ordered-dict@1.0.3
jquery@1.11.4
jquery-waypoints@1.0.4
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
localstorage@1.0.4
logging@1.0.8
mdg:camera@1.2.0
mdg:geolocation@1.1.0
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-mongo@1.4.39_1
oauth@1.1.6
oauth1@1.1.5
observe-sequence@1.0.7
ordered-dict@1.0.4
percolate:velocityjs@1.2.1_1
percolate:wireframing@0.2.0
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
service-configuration@1.0.4
session@1.1.0
spacebars@1.0.6
spacebars-compiler@1.0.6
templating@1.1.1
tmeasday:publish-counts@0.3.4
tracker@1.0.7
twitter@1.1.4
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
promise@0.4.8
random@1.0.4
rate-limit@1.0.0
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
spacebars@1.0.7
spacebars-compiler@1.0.7
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tmeasday:publish-counts@0.7.2
tracker@1.0.8
twitter@1.1.5
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -7,3 +7,6 @@ notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -0,0 +1 @@
local

View File

@@ -0,0 +1,23 @@
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
accounts-ui
accounts-password
standard-minifiers
meteor-base
mobile-experience
mongo
blaze-html-templates
session
jquery
tracker
logging
reload
random
ejson
spacebars
check
angular

View File

@@ -0,0 +1,2 @@
server
browser

View File

@@ -0,0 +1 @@
METEOR@1.2

View File

@@ -0,0 +1,80 @@
accounts-base@1.2.1
accounts-password@1.1.2
accounts-ui@1.1.6
accounts-ui-unstyled@1.1.8
angular@1.0.0-rc.6
angular:angular@1.4.6
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
dburles:mongo-collection-instances@0.3.4
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
jquery@1.11.4
lai:collection-extensions@0.1.4
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
localstorage@1.0.4
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-bcrypt@0.7.8_2
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
rate-limit@1.0.0
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -0,0 +1,9 @@
# Simple Todo List
The Meteor Tutorial app, angular-meteor version.
Use it to share a single todo list with your friends. The list updates on everyone's screen in real time, and you can make tasks private if you don't want others to see them.
Learn how to build this app by following the [Meteor Tutorial - Angular version](https://www.meteor.com/tutorials/angular/creating-an-app).
![screenshot](https://github.com/meteor/simple-todos/blob/master/screenshot.png)

View File

@@ -0,0 +1,127 @@
/* CSS declarations go here */
body {
font-family: sans-serif;
background-color: #315481;
background-image: linear-gradient(to bottom, #315481, #918e82 100%);
background-attachment: fixed;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0;
margin: 0;
font-size: 14px;
}
.container {
max-width: 600px;
margin: 0 auto;
min-height: 100%;
background: white;
}
header {
background: #d2edf4;
background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%);
padding: 20px 15px 15px 15px;
position: relative;
}
#login-buttons {
display: block;
}
h1 {
font-size: 1.5em;
margin: 0;
margin-bottom: 10px;
display: inline-block;
margin-right: 1em;
}
form {
margin-top: 10px;
margin-bottom: -10px;
position: relative;
}
.new-task input {
box-sizing: border-box;
padding: 10px 0;
background: transparent;
border: none;
width: 100%;
padding-right: 80px;
font-size: 1em;
}
.new-task input:focus{
outline: 0;
}
ul {
margin: 0;
padding: 0;
background: white;
}
.delete {
float: right;
font-weight: bold;
background: none;
font-size: 1em;
border: none;
position: relative;
}
li {
position: relative;
list-style: none;
padding: 15px;
border-bottom: #eee solid 1px;
}
li .text {
margin-left: 10px;
}
li.checked {
color: #888;
}
li.checked .text {
text-decoration: line-through;
}
li.private {
background: #eee;
border-color: #ddd;
}
header .hide-completed {
float: right;
}
.toggle-private {
margin-left: 5px;
}
@media (max-width: 600px) {
li {
padding: 12px 15px;
}
.search {
width: 150px;
clear: both;
}
.new-task input {
padding-bottom: 5px;
}
}

View File

@@ -0,0 +1,7 @@
<head>
<title>Todo List</title>
</head>
<body ng-include="'todos-list.ng.html'"
ng-controller="TodosListCtrl">
</body>

View File

@@ -0,0 +1,113 @@
Tasks = new Mongo.Collection('tasks');
if (Meteor.isClient) {
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
// This code only runs on the client
angular.module('simple-todos',['angular-meteor']);
function onReady() {
angular.bootstrap(document, ['simple-todos']);
}
if (Meteor.isCordova)
angular.element(document).on('deviceready', onReady);
else
angular.element(document).ready(onReady);
angular.module('simple-todos').controller('TodosListCtrl', ['$scope', '$meteor',
function ($scope, $meteor) {
$scope.$meteorSubscribe('tasks');
$scope.tasks = $meteor.collection(function() {
return Tasks.find($scope.getReactively('query'), {sort: {createdAt: -1}})
});
$scope.addTask = function (newTask) {
$meteor.call('addTask', newTask);
};
$scope.deleteTask = function (task) {
$meteor.call('deleteTask', task._id);
};
$scope.setChecked = function (task) {
$meteor.call('setChecked', task._id, !task.checked);
};
$scope.setPrivate = function (task) {
$meteor.call('setPrivate', task._id, ! task.private);
};
$scope.$watch('hideCompleted', function() {
if ($scope.hideCompleted)
$scope.query = {checked: {$ne: true}};
else
$scope.query = {};
});
$scope.incompleteCount = function () {
return Tasks.find({ checked: {$ne: true} }).count();
};
}]);
}
Meteor.methods({
addTask: function (text) {
// Make sure the user is logged in before inserting a task
if (! Meteor.userId()) {
throw new Meteor.Error('not-authorized');
}
Tasks.insert({
text: text,
createdAt: new Date(),
owner: Meteor.userId(),
username: Meteor.user().username
});
},
deleteTask: function (taskId) {
var task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can delete it
throw new Meteor.Error('not-authorized');
}
Tasks.remove(taskId);
},
setChecked: function (taskId, setChecked) {
var task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can check it off
throw new Meteor.Error('not-authorized');
}
Tasks.update(taskId, { $set: { checked: setChecked} });
},
setPrivate: function (taskId, setToPrivate) {
var task = Tasks.findOne(taskId);
// Make sure only the task owner can make a task private
if (task.owner !== Meteor.userId()) {
throw new Meteor.Error('not-authorized');
}
Tasks.update(taskId, { $set: { private: setToPrivate } });
}
});
if (Meteor.isServer) {
Meteor.publish('tasks', function () {
return Tasks.find({
$or: [
{ private: {$ne: true} },
{ owner: this.userId }
]
});
});
}

View File

@@ -0,0 +1,39 @@
<div class="container">
<header>
<h1>Todo List ( {{ incompleteCount() }} )</h1>
<label class="hide-completed">
<input type="checkbox" ng-model="$parent.hideCompleted"/>
Hide Completed Tasks
</label>
<meteor-include src="loginButtons"></meteor-include>
<!-- add a form below the h1 -->
<form class="new-task"
ng-submit="addTask(newTask); newTask='';"
ng-show="$root.currentUser">
<input ng-model="newTask" type="text"
name="text" placeholder="Type to add new tasks" />
</form>
</header>
<ul ng-repeat="task in tasks">
<li ng-class="{'checked': task.checked, 'private': task.private}">
<button class="delete" ng-click="deleteTask(task)">&times;</button>
<input type="checkbox" ng-checked="task.checked"
ng-click="setChecked(task)" class="toggle-checked" />
<button class="toggle-private"
ng-if="task.owner === $root.currentUser._id"
ng-click="setPrivate(task)">
{{task.private == true ? "Private" : "Public"}}
</button>
<span class="text">
<strong>{{task.username}}</strong> - {{task.text}}
</span>
</li>
</ul>
</div>

View File

@@ -7,3 +7,6 @@ notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -0,0 +1 @@
local

View File

@@ -0,0 +1,23 @@
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
react
accounts-ui
accounts-password
standard-minifiers
meteor-base
mobile-experience
mongo
blaze-html-templates
session
jquery
tracker
logging
reload
random
ejson
spacebars
check

View File

@@ -0,0 +1,2 @@
server
browser

View File

@@ -0,0 +1 @@
METEOR@1.2

View File

@@ -0,0 +1,84 @@
accounts-base@1.2.1
accounts-password@1.1.2
accounts-ui@1.1.6
accounts-ui-unstyled@1.1.8
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
coffeescript@1.0.8
cosmos:browserify@0.5.1
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
jquery@1.11.4
jsx@0.2.1
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
localstorage@1.0.4
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-bcrypt@0.7.8_2
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
rate-limit@1.0.0
react@0.1.13
react-meteor-data@0.1.9
react-runtime@0.13.3_7
react-runtime-dev@0.13.3_7
react-runtime-prod@0.13.3_6
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -0,0 +1,15 @@
AccountsUIWrapper = React.createClass({
componentDidMount() {
// Use Meteor Blaze to render login buttons
this.view = Blaze.render(Template.loginButtons,
React.findDOMNode(this.refs.container));
},
componentWillUnmount() {
// Clean up Blaze view
Blaze.remove(this.view);
},
render() {
// Just render a placeholder container that will be filled in
return <span ref="container" />;
}
});

View File

@@ -0,0 +1,93 @@
// App component - represents the whole app
App = React.createClass({
// This mixin makes the getMeteorData method work
mixins: [ReactMeteorData],
getInitialState() {
return {
hideCompleted: false
}
},
// Loads items from the Tasks collection and puts them on this.data.tasks
getMeteorData() {
let query = {};
if (this.state.hideCompleted) {
// If hide completed is checked, filter tasks
query = {checked: {$ne: true}};
}
return {
tasks: Tasks.find(query, {sort: {createdAt: -1}}).fetch(),
incompleteCount: Tasks.find({checked: {$ne: true}}).count(),
currentUser: Meteor.user()
};
},
renderTasks() {
// Get tasks from this.data.tasks
return this.data.tasks.map((task) => {
const currentUserId = this.data.currentUser && this.data.currentUser._id;
const showPrivateButton = task.owner === currentUserId;
return <Task
key={task._id}
task={task}
showPrivateButton={showPrivateButton} />;
});
},
handleSubmit(event) {
event.preventDefault();
// Find the text field via the React ref
var text = React.findDOMNode(this.refs.textInput).value.trim();
Meteor.call("addTask", text);
// Clear form
React.findDOMNode(this.refs.textInput).value = "";
},
toggleHideCompleted() {
this.setState({
hideCompleted: ! this.state.hideCompleted
});
},
render() {
return (
<div className="container">
<header>
<h1>Todo List ({this.data.incompleteCount})</h1>
<label className="hide-completed">
<input
type="checkbox"
readOnly={true}
checked={this.state.hideCompleted}
onClick={this.toggleHideCompleted} />
Hide Completed Tasks
</label>
<AccountsUIWrapper />
{ this.data.currentUser ?
<form className="new-task" onSubmit={this.handleSubmit} >
<input
type="text"
ref="textInput"
placeholder="Type to add new tasks" />
</form> : ''
}
</header>
<ul>
{this.renderTasks()}
</ul>
</div>
);
}
});

View File

@@ -0,0 +1,22 @@
========================================
Meteor is licensed under the MIT License
========================================
Copyright (C) 2011--2015 Meteor Development Group
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,9 @@
# Simple Todo List
The Meteor Tutorial app.
Use it to share a single todo list with your friends. The list updates on everyone's screen in real time, and you can make tasks private if you don't want others to see them.
Learn how to build this app by following the [Meteor Tutorial](http://www.meteor.com/install).
![screenshot](screenshot.png)

View File

@@ -0,0 +1,52 @@
// Task component - represents a single todo item
Task = React.createClass({
propTypes: {
task: React.PropTypes.object.isRequired,
showPrivateButton: React.PropTypes.bool.isRequired
},
toggleChecked() {
// Set the checked property to the opposite of its current value
Meteor.call("setChecked", this.props.task._id, ! this.props.task.checked);
},
deleteThisTask() {
Meteor.call("removeTask", this.props.task._id);
},
togglePrivate() {
Meteor.call("setPrivate", this.props.task._id, ! this.props.task.private);
},
render() {
// Give tasks a different className when they are checked off,
// so that we can style them nicely in CSS
// Add "checked" and/or "private" to the className when needed
const taskClassName = (this.props.task.checked ? "checked" : "") + " " +
(this.props.task.private ? "private" : "");
return (
<li className={taskClassName}>
<button className="delete" onClick={this.deleteThisTask}>
&times;
</button>
<input
type="checkbox"
readOnly={true}
checked={this.props.task.checked}
onClick={this.toggleChecked} />
{ this.props.showPrivateButton ? (
<button className="toggle-private" onClick={this.togglePrivate}>
{ this.props.task.private ? "Private" : "Public" }
</button>
) : ''}
<span className="text">
<strong>{this.props.task.username}</strong>: {this.props.task.text}
</span>
</li>
);
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

View File

@@ -0,0 +1,126 @@
/* CSS declarations go here */
body {
font-family: sans-serif;
background-color: #315481;
background-image: linear-gradient(to bottom, #315481, #918e82 100%);
background-attachment: fixed;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0;
margin: 0;
font-size: 14px;
}
.container {
max-width: 600px;
margin: 0 auto;
min-height: 100%;
background: white;
}
header {
background: #d2edf4;
background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%);
padding: 20px 15px 15px 15px;
position: relative;
}
#login-buttons {
display: block;
}
h1 {
font-size: 1.5em;
margin: 0;
margin-bottom: 10px;
display: inline-block;
margin-right: 1em;
}
form {
margin-top: 10px;
margin-bottom: -10px;
position: relative;
}
.new-task input {
box-sizing: border-box;
padding: 10px 0;
background: transparent;
border: none;
width: 100%;
padding-right: 80px;
font-size: 1em;
}
.new-task input:focus{
outline: 0;
}
ul {
margin: 0;
padding: 0;
background: white;
}
.delete {
float: right;
font-weight: bold;
background: none;
font-size: 1em;
border: none;
position: relative;
}
li {
position: relative;
list-style: none;
padding: 15px;
border-bottom: #eee solid 1px;
}
li .text {
margin-left: 10px;
}
li.checked {
color: #888;
}
li.checked .text {
text-decoration: line-through;
}
li.private {
background: #eee;
border-color: #ddd;
}
header .hide-completed {
float: right;
}
.toggle-private {
margin-left: 5px;
}
@media (max-width: 600px) {
li {
padding: 12px 15px;
}
.search {
width: 150px;
clear: both;
}
.new-task input {
padding-bottom: 5px;
}
}

View File

@@ -0,0 +1,7 @@
<head>
<title>Todo List</title>
</head>
<body>
<div id="render-target"></div>
</body>

View File

@@ -0,0 +1,75 @@
// Define a collection to hold our tasks
Tasks = new Mongo.Collection("tasks");
if (Meteor.isClient) {
// This code is executed on the client only
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
Meteor.subscribe("tasks");
Meteor.startup(function () {
// Use Meteor.startup to render the component after the page is ready
React.render(<App />, document.getElementById("render-target"));
});
}
if (Meteor.isServer) {
// Only publish tasks that are public or belong to the current user
Meteor.publish("tasks", function () {
return Tasks.find({
$or: [
{ private: {$ne: true} },
{ owner: this.userId }
]
});
});
}
Meteor.methods({
addTask(text) {
// Make sure the user is logged in before inserting a task
if (! Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Tasks.insert({
text: text,
createdAt: new Date(),
owner: Meteor.userId(),
username: Meteor.user().username
});
},
removeTask(taskId) {
const task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can delete it
throw new Meteor.Error("not-authorized");
}
Tasks.remove(taskId);
},
setChecked(taskId, setChecked) {
const task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can check it off
throw new Meteor.Error("not-authorized");
}
Tasks.update(taskId, { $set: { checked: setChecked} });
},
setPrivate(taskId, setToPrivate) {
const task = Tasks.findOne(taskId);
// Make sure only the task owner can make a task private
if (task.owner !== Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Tasks.update(taskId, { $set: { private: setToPrivate } });
}
});

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -0,0 +1 @@
local

View File

@@ -0,0 +1,22 @@
# Meteor packages used by this project, one per line.
# Check this file (and the other files in this directory) into your repository.
#
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
accounts-ui
accounts-password
standard-minifiers
meteor-base
mobile-experience
mongo
blaze-html-templates
session
jquery
tracker
logging
reload
random
ejson
spacebars
check

View File

@@ -0,0 +1,2 @@
server
browser

View File

@@ -0,0 +1 @@
METEOR@1.2

View File

@@ -0,0 +1,76 @@
accounts-base@1.2.1
accounts-password@1.1.2
accounts-ui@1.1.6
accounts-ui-unstyled@1.1.8
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
jquery@1.11.4
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
localstorage@1.0.4
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-bcrypt@0.7.8_2
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
rate-limit@1.0.0
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -0,0 +1,22 @@
========================================
Meteor is licensed under the MIT License
========================================
Copyright (C) 2011--2015 Meteor Development Group
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,9 @@
# Simple Todo List
The Meteor Tutorial app.
Use it to share a single todo list with your friends. The list updates on everyone's screen in real time, and you can make tasks private if you don't want others to see them.
Learn how to build this app by following the [Meteor Tutorial](http://www.meteor.com/install).
![screenshot](screenshot.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

View File

@@ -0,0 +1,126 @@
/* CSS declarations go here */
body {
font-family: sans-serif;
background-color: #315481;
background-image: linear-gradient(to bottom, #315481, #918e82 100%);
background-attachment: fixed;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0;
margin: 0;
font-size: 14px;
}
.container {
max-width: 600px;
margin: 0 auto;
min-height: 100%;
background: white;
}
header {
background: #d2edf4;
background-image: linear-gradient(to bottom, #d0edf5, #e1e5f0 100%);
padding: 20px 15px 15px 15px;
position: relative;
}
#login-buttons {
display: block;
}
h1 {
font-size: 1.5em;
margin: 0;
margin-bottom: 10px;
display: inline-block;
margin-right: 1em;
}
form {
margin-top: 10px;
margin-bottom: -10px;
position: relative;
}
.new-task input {
box-sizing: border-box;
padding: 10px 0;
background: transparent;
border: none;
width: 100%;
padding-right: 80px;
font-size: 1em;
}
.new-task input:focus{
outline: 0;
}
ul {
margin: 0;
padding: 0;
background: white;
}
.delete {
float: right;
font-weight: bold;
background: none;
font-size: 1em;
border: none;
position: relative;
}
li {
position: relative;
list-style: none;
padding: 15px;
border-bottom: #eee solid 1px;
}
li .text {
margin-left: 10px;
}
li.checked {
color: #888;
}
li.checked .text {
text-decoration: line-through;
}
li.private {
background: #eee;
border-color: #ddd;
}
header .hide-completed {
float: right;
}
.toggle-private {
margin-left: 5px;
}
@media (max-width: 600px) {
li {
padding: 12px 15px;
}
.search {
width: 150px;
clear: both;
}
.new-task input {
padding-bottom: 5px;
}
}

View File

@@ -0,0 +1,50 @@
<head>
<title>Todo List</title>
</head>
<body>
<div class="container">
<header>
<h1>Todo List ({{incompleteCount}})</h1>
<label class="hide-completed">
<input type="checkbox" checked="{{hideCompleted}}" />
Hide Completed Tasks
</label>
{{> loginButtons}}
{{#if currentUser}}
<form class="new-task">
<input type="text" name="text" placeholder="Type to add new tasks" />
</form>
{{/if}}
</header>
<ul>
{{#each tasks}}
{{> task}}
{{/each}}
</ul>
</div>
</body>
<template name="task">
<li class="{{#if checked}}checked{{/if}} {{#if private}}private{{/if}}">
<button class="delete">&times;</button>
<input type="checkbox" checked="{{checked}}" class="toggle-checked" />
{{#if isOwner}}
<button class="toggle-private">
{{#if private}}
Private
{{else}}
Public
{{/if}}
</button>
{{/if}}
<span class="text"><strong>{{username}}</strong> - {{text}}</span>
</li>
</template>

View File

@@ -0,0 +1,123 @@
Tasks = new Mongo.Collection("tasks");
if (Meteor.isServer) {
// This code only runs on the server
// Only publish tasks that are public or belong to the current user
Meteor.publish("tasks", function () {
return Tasks.find({
$or: [
{ private: {$ne: true} },
{ owner: this.userId }
]
});
});
}
if (Meteor.isClient) {
// This code only runs on the client
Meteor.subscribe("tasks");
Template.body.helpers({
tasks: function () {
if (Session.get("hideCompleted")) {
// If hide completed is checked, filter tasks
return Tasks.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
} else {
// Otherwise, return all of the tasks
return Tasks.find({}, {sort: {createdAt: -1}});
}
},
hideCompleted: function () {
return Session.get("hideCompleted");
},
incompleteCount: function () {
return Tasks.find({checked: {$ne: true}}).count();
}
});
Template.body.events({
"submit .new-task": function (event) {
// Prevent default browser form submit
event.preventDefault();
// Get value from form element
var text = event.target.text.value;
// Insert a task into the collection
Meteor.call("addTask", text);
// Clear form
event.target.text.value = "";
},
"change .hide-completed input": function (event) {
Session.set("hideCompleted", event.target.checked);
}
});
Template.task.helpers({
isOwner: function () {
return this.owner === Meteor.userId();
}
});
Template.task.events({
"click .toggle-checked": function () {
// Set the checked property to the opposite of its current value
Meteor.call("setChecked", this._id, ! this.checked);
},
"click .delete": function () {
Meteor.call("deleteTask", this._id);
},
"click .toggle-private": function () {
Meteor.call("setPrivate", this._id, ! this.private);
}
});
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
}
Meteor.methods({
addTask: function (text) {
// Make sure the user is logged in before inserting a task
if (! Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Tasks.insert({
text: text,
createdAt: new Date(),
owner: Meteor.userId(),
username: Meteor.user().username
});
},
deleteTask: function (taskId) {
var task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can delete it
throw new Meteor.Error("not-authorized");
}
Tasks.remove(taskId);
},
setChecked: function (taskId, setChecked) {
var task = Tasks.findOne(taskId);
if (task.private && task.owner !== Meteor.userId()) {
// If the task is private, make sure only the owner can check it off
throw new Meteor.Error("not-authorized");
}
Tasks.update(taskId, { $set: { checked: setChecked} });
},
setPrivate: function (taskId, setToPrivate) {
var task = Tasks.findOne(taskId);
// Make sure only the task owner can make a task private
if (task.owner !== Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Tasks.update(taskId, { $set: { private: setToPrivate } });
}
});

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -1 +1 @@
METEOR@1.1.0.3
METEOR@1.2

View File

@@ -1,60 +1,79 @@
accounts-base@1.2.0
accounts-password@1.1.1
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
email@1.0.6
fastclick@1.0.3
geojson-utils@1.0.3
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
insecure@1.0.3
accounts-base@1.2.1
accounts-password@1.1.2
autoupdate@1.2.3
babel-compiler@5.8.24
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.1
callback-hook@1.0.4
check@1.0.6
ddp@1.2.1
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.8
diff-sequence@1.0.1
ecmascript@0.1.3
ecmascript-collections@0.1.6
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
geojson-utils@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
insecure@1.0.4
iron:core@0.3.4
iron:dynamic-template@0.4.1
iron:layout@0.4.1
iron:router@0.9.4
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
less@1.0.14
livedata@1.0.13
localstorage@1.0.3
logging@1.0.7
meteor@1.1.6
meteor-platform@1.2.2
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
jquery@1.11.4
launch-screen@1.0.3
less@2.5.0_1
livedata@1.0.14
localstorage@1.0.4
logging@1.0.8
meteor@1.1.7
meteor-base@1.0.1
minifiers@1.1.6
minimongo@1.0.9
mobile-experience@1.0.1
mobile-status-bar@1.0.6
mongo@1.1.1
mongo-id@1.0.1
npm-bcrypt@0.7.8_2
observe-sequence@1.0.6
ordered-dict@1.0.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
service-configuration@1.0.4
session@1.1.0
sha@1.0.3
spacebars@1.0.6
spacebars-compiler@1.0.6
srp@1.0.3
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
webapp@1.2.0
webapp-hashing@1.0.3
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
promise@0.4.8
random@1.0.4
rate-limit@1.0.0
reactive-dict@1.1.1
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.0
templating@1.1.2
templating-tools@1.0.0
tracker@1.0.8
ui@1.0.7
underscore@1.0.4
url@1.0.5
webapp@1.2.2
webapp-hashing@1.0.4

View File

@@ -5,7 +5,7 @@ Ap.removeDefaultRateLimit = function () {
const resp = DDPRateLimiter.removeRule(defaultRateLimiterRuleId);
defaultRateLimiterRuleId = null;
return resp;
}
};
// Add a default rule of limiting logins, creating new users and password reset
// to 5 times every 10 seconds per connection.
@@ -24,6 +24,6 @@ Ap.addDefaultRateLimit = function () {
}
}, 5, 10000);
}
}
};
Ap.addDefaultRateLimit();
Ap.addDefaultRateLimit();

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "A user account system",
version: "1.2.1-plugins.0"
version: "1.2.1"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Facebook accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Github accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Google accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Meetup accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Meteor developer accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Common code for OAuth-based login services",
version: "1.1.6-plugins.0"
version: "1.1.6"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Password support for accounts",
version: "1.1.2-plugins.0"
version: "1.1.2"
});
Package.onUse(function(api) {

View File

@@ -130,8 +130,6 @@ Accounts.createUser = function (options, callback) {
});
};
// Change password. Must be logged in.
//
// @param oldPassword {String|null} By default servers no longer allow

View File

@@ -77,13 +77,7 @@ var checkPassword = Accounts._checkPassword;
/// LOGIN
///
// Attempts to find a user from a user query.
// First tries to match username or email case sensitively; if that fails, it
// tries case insensitively; but if more than one user matches the case
// insensitive search, it returns null
// @param query {Object} with one of `id`, `username`, or `email`.
// @returns A user if found, else null
var findUserFromQuery = function (query) {
Accounts._findUserByQuery = function (query) {
var user = null;
if (query.id) {
@@ -110,8 +104,6 @@ var findUserFromQuery = function (query) {
// No match if multiple candidates are found
if (candidateUsers.length === 1) {
user = candidateUsers[0];
} else {
console.error('Found multiple users with ' + fieldName + ' = ' + fieldValue + ' only differing in case. Requiring case sensitive login.');
}
}
}
@@ -119,6 +111,35 @@ var findUserFromQuery = function (query) {
return user;
};
/**
* @summary Finds the user with the specified username.
* First tries to match username case sensitively; if that fails, it
* tries case insensitively; but if more than one user matches the case
* insensitive search, it returns null.
* @locus Server
* @param {String} username The username to look for
* @returns {Object} A user if found, else null
*/
Accounts.findUserByUsername = function (username) {
return Accounts._findUserByQuery({
username: username
});
};
/**
* @summary Finds the user with the specified email.
* First tries to match email case sensitively; if that fails, it
* tries case insensitively; but if more than one user matches the case
* insensitive search, it returns null.
* @locus Server
* @param {String} email The email address to look for
* @returns {Object} A user if found, else null
*/
Accounts.findUserByEmail = function (email) {
return Accounts._findUserByQuery({
email: email
});
};
// Generates a MongoDB selector that can be used to perform a fast case
// insensitive lookup for the given fieldName and string. Since MongoDB does
@@ -164,6 +185,26 @@ var generateCasePermutationsForString = function (string) {
return permutations;
}
var checkForCaseInsensitiveDuplicates = function (fieldName, displayName, fieldValue, ownUserId) {
// Some tests need the ability to add users with the same case insensitive
// value, hence the _skipCaseInsensitiveChecksForTest check
var skipCheck = _.has(Accounts._skipCaseInsensitiveChecksForTest, fieldValue);
if (fieldValue && !skipCheck) {
var matchedUsers = Meteor.users.find(
selectorForFastCaseInsensitiveLookup(fieldName, fieldValue)).fetch();
if (matchedUsers.length > 0 &&
// If we don't have a userId yet, any match we find is a duplicate
(!ownUserId ||
// Otherwise, check to see if there are multiple matches or a match
// that is not us
(matchedUsers.length > 1 || matchedUsers[0]._id !== ownUserId))) {
throw new Meteor.Error(403, displayName + " already exists.");
}
}
};
// XXX maybe this belongs in the check package
var NonEmptyString = Match.Where(function (x) {
check(x, String);
@@ -210,7 +251,7 @@ Accounts.registerLoginHandler("password", function (options) {
});
var user = findUserFromQuery(options.user);
var user = Accounts._findUserByQuery(options.user);
if (!user)
throw new Meteor.Error(403, "User not found");
@@ -276,7 +317,7 @@ Accounts.registerLoginHandler("password", function (options) {
password: passwordValidator
});
var user = findUserFromQuery(options.user);
var user = Accounts._findUserByQuery(options.user);
if (!user)
throw new Meteor.Error(403, "User not found");
@@ -320,6 +361,40 @@ Accounts.registerLoginHandler("password", function (options) {
/// CHANGING
///
/**
* @summary Change a user's username. Use this instead of updating the
* database directly. The operation will fail if there is an existing user
* with a username only differing in case.
* @locus Server
* @param {String} userId The ID of the user to update.
* @param {String} newUsername A new username for the user.
*/
Accounts.setUsername = function (userId, newUsername) {
check(userId, NonEmptyString);
check(newUsername, NonEmptyString);
var user = Meteor.users.findOne(userId);
if (!user)
throw new Meteor.Error(403, "User not found");
var oldUsername = user.username;
// Perform a case insensitive check fro duplicates before update
checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);
Meteor.users.update({_id: user._id}, {$set: {username: newUsername}});
// Perform another check after update, in case a matching user has been
// inserted in the meantime
try {
checkForCaseInsensitiveDuplicates('username', 'Username', newUsername, user._id);
} catch (ex) {
// Undo update if the check fails
Meteor.users.update({_id: user._id}, {$set: {username: oldUsername}});
throw ex;
}
};
// Let the user change their own password if they know the old
// password. `oldPassword` and `newPassword` should be objects with keys
// `digest` and `algorithm` (representing the SHA256 of the password).
@@ -758,7 +833,111 @@ Meteor.methods({verifyEmail: function (token) {
);
}});
/**
* @summary Add an email address for a user. Use this instead of directly
* updating the database. The operation will fail if there is a different user
* with an email only differing in case. If the specified user has an existing
* email only differing in case however, we replace it.
* @locus Server
* @param {String} userId The ID of the user to update.
* @param {String} newEmail A new email address for the user.
* @param {Boolean} [verified] Optional - whether the new email address should
* be marked as verified. Defaults to false.
*/
Accounts.addEmail = function (userId, newEmail, verified) {
check(userId, NonEmptyString);
check(newEmail, NonEmptyString);
check(verified, Match.Optional(Boolean));
if (_.isUndefined(verified)) {
verified = false;
}
var user = Meteor.users.findOne(userId);
if (!user)
throw new Meteor.Error(403, "User not found");
// Allow users to change their own email to a version with a different case
// We don't have to call checkForCaseInsensitiveDuplicates to do a case
// insensitive check across all emails in the database here because: (1) if
// there is no case-insensitive duplicate between this user and other users,
// then we are OK and (2) if this would create a conflict with other users
// then there would already be a case-insensitive duplicate and we can't fix
// that in this code anyway.
var caseInsensitiveRegExp =
new RegExp('^' + Meteor._escapeRegExp(newEmail) + '$', 'i');
var didUpdateOwnEmail = _.any(user.emails, function(email, index) {
if (caseInsensitiveRegExp.test(email.address)) {
Meteor.users.update({
_id: user._id,
'emails.address': email.address
}, {$set: {
'emails.$.address': newEmail,
'emails.$.verified': verified
}});
return true;
}
return false;
});
// In the other updates below, we have to do another call to
// checkForCaseInsensitiveDuplicates to make sure that no conflicting values
// were added to the database in the meantime. We don't have to do this for
// the case where the user is updating their email address to one that is the
// same as before, but only different because of capitalization. Read the
// big comment above to understand why.
if (didUpdateOwnEmail) {
return;
}
// Perform a case insensitive check for duplicates before update
checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);
Meteor.users.update({
_id: user._id
}, {
$addToSet: {
emails: {
address: newEmail,
verified: verified
}
}
});
// Perform another check after update, in case a matching user has been
// inserted in the meantime
try {
checkForCaseInsensitiveDuplicates('emails.address', 'Email', newEmail, user._id);
} catch (ex) {
// Undo update if the check fails
Meteor.users.update({_id: user._id},
{$pull: {emails: {address: newEmail}}});
throw ex;
}
}
/**
* @summary Remove an email address for a user. Use this instead of updating
* the database directly.
* @locus Server
* @param {String} userId The ID of the user to update.
* @param {String} email The email address to remove.
*/
Accounts.removeEmail = function (userId, email) {
check(userId, NonEmptyString);
check(email, NonEmptyString);
var user = Meteor.users.findOne(userId);
if (!user)
throw new Meteor.Error(403, "User not found");
Meteor.users.update({_id: user._id},
{$pull: {emails: {address: email}}});
}
///
/// CREATING USERS
@@ -794,34 +973,16 @@ var createUser = function (options) {
if (email)
user.emails = [{address: email, verified: false}];
// Check if there is no other user with a username or email only differing
// in case.
var performCaseInsensitiveCheck = function () {
// Some tests need the ability to add users with the same case insensitive
// username or email, hence the _skipCaseInsensitiveChecksForTest check
if (username &&
!_.has(Accounts._skipCaseInsensitiveChecksForTest, username) &&
Meteor.users.find(selectorForFastCaseInsensitiveLookup(
"username", username)).count() > 1) {
throw new Meteor.Error(403, "Username already exists.");
}
if (email &&
!_.has(Accounts._skipCaseInsensitiveChecksForTest, email) &&
Meteor.users.find(selectorForFastCaseInsensitiveLookup(
"emails.address", email)).count() > 1) {
throw new Meteor.Error(403, "Email already exists.");
}
}
// Perform a case insensitive check before insert
performCaseInsensitiveCheck();
checkForCaseInsensitiveDuplicates('username', 'Username', username);
checkForCaseInsensitiveDuplicates('emails.address', 'Email', email);
var userId = Accounts.insertUserDoc(options, user);
// Perform another check after insert, in case a matching user has been
// inserted in the meantime
try {
performCaseInsensitiveCheck();
checkForCaseInsensitiveDuplicates('username', 'Username', username, userId);
checkForCaseInsensitiveDuplicates('emails.address', 'Email', email, userId);
} catch (ex) {
// Remove inserted user if the check fails
Meteor.users.remove(userId);

View File

@@ -2,9 +2,6 @@ Accounts._noConnectionCloseDelayForTest = true;
Accounts.removeDefaultRateLimit();
if (Meteor.isServer) {
Meteor.methods({
getUserId: function () {
return this.userId;
},
getResetToken: function () {
var token = Meteor.users.findOne(this.userId).services.password.reset;
return token;
@@ -48,14 +45,29 @@ if (Meteor.isClient) (function () {
};
var logoutStep = function (test, expect) {
Meteor.logout(expect(function (error) {
test.equal(error, undefined);
if (error) {
test.fail(error.message);
}
test.equal(Meteor.user(), null);
}));
};
var loggedInAs = function (someUsername, test, expect) {
return expect(function (error) {
test.equal(error, undefined);
test.equal(Meteor.user().username, someUsername);
if (error) {
test.fail(error.message);
}
test.equal(Meteor.userId() && Meteor.user().username, someUsername);
});
};
var loggedInUserHasEmail = function (someEmail, test, expect) {
return expect(function (error) {
if (error) {
test.fail(error.message);
}
var user = Meteor.user();
test.isTrue(user && _.some(user.emails, function(email) {
return email.address === someEmail;
}));
});
};
var expectError = function (expectedError, test, expect) {
@@ -74,17 +86,23 @@ if (Meteor.isClient) (function () {
};
var invalidateLoginsStep = function (test, expect) {
Meteor.call("testInvalidateLogins", 'fail', expect(function (error) {
test.isFalse(error);
if (error) {
test.fail(error.message);
}
}));
};
var hideActualLoginErrorStep = function (test, expect) {
Meteor.call("testInvalidateLogins", 'hide', expect(function (error) {
test.isFalse(error);
if (error) {
test.fail(error.message);
}
}));
};
var validateLoginsStep = function (test, expect) {
Meteor.call("testInvalidateLogins", false, expect(function (error) {
test.isFalse(error);
if (error) {
test.fail(error.message);
}
}));
};
@@ -206,7 +224,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive username with non-ASCII characters", [
testAsyncMulti("passwords - logging in with case insensitive username " +
"with non-ASCII characters", [
function (test, expect) {
// Hack because Tinytest does not clean the database between tests/runs
this.randomSuffix = Random.id(10);
@@ -226,7 +245,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive username should escape regex special characters", [
testAsyncMulti("passwords - logging in with case insensitive username " +
"should escape regex special characters", [
createUserStep,
logoutStep,
// We shouldn't be able to log in with a regex expression for the username
@@ -238,7 +258,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive username should require a match of the full string", [
testAsyncMulti("passwords - logging in with case insensitive username " +
"should require a match of the full string", [
createUserStep,
logoutStep,
// We shouldn't be able to log in with a partial match for the username
@@ -250,21 +271,22 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive username when there are multiple matches", [
testAsyncMulti("passwords - logging in with case insensitive username when " +
"there are multiple matches", [
createUserStep,
logoutStep,
function (test, expect) {
this.otherUserName = 'Adalovelace' + this.randomSuffix;
addSkipCaseInsensitiveChecksForTest(this.otherUserName, test, expect);
this.otherUsername = 'Adalovelace' + this.randomSuffix;
addSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);
},
// Create another user with a username that only differs in case
function (test, expect) {
Accounts.createUser(
{ username: this.otherUserName, password: this.password },
loggedInAs(this.otherUserName, test, expect));
{ username: this.otherUsername, password: this.password },
loggedInAs(this.otherUsername, test, expect));
},
function (test, expect) {
removeSkipCaseInsensitiveChecksForTest(this.otherUserName, test, expect);
removeSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);
},
// We shouldn't be able to log in with the username in lower case
function (test, expect) {
@@ -282,7 +304,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - creating users with the same case insensitive username", [
testAsyncMulti("passwords - creating users with the same case insensitive " +
"username", [
createUserStep,
logoutStep,
// Attempting to create another user with a username that only differs in
@@ -318,7 +341,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive email should escape regex special characters", [
testAsyncMulti("passwords - logging in with case insensitive email should " +
"escape regex special characters", [
createUserStep,
logoutStep,
// We shouldn't be able to log in with a regex expression for the email
@@ -330,7 +354,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive email should require a match of the full string", [
testAsyncMulti("passwords - logging in with case insensitive email should " +
"require a match of the full string", [
createUserStep,
logoutStep,
// We shouldn't be able to log in with a partial match for the email
@@ -342,24 +367,25 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - logging in with case insensitive email when there are multiple matches", [
testAsyncMulti("passwords - logging in with case insensitive email when " +
"there are multiple matches", [
createUserStep,
logoutStep,
function (test, expect) {
this.otherUserName = 'AdaLovelace' + Random.id(10);
this.otherUsername = 'AdaLovelace' + Random.id(10);
this.otherEmail = "ADA-intercept@lovelace.com" + this.randomSuffix;
addSkipCaseInsensitiveChecksForTest(this.otherEmail, test, expect);
},
// Create another user with an email that only differs in case
function (test, expect) {
Accounts.createUser(
{ username: this.otherUserName,
{ username: this.otherUsername,
email: this.otherEmail,
password: this.password },
loggedInAs(this.otherUserName, test, expect));
loggedInAs(this.otherUsername, test, expect));
},
function (test, expect) {
removeSkipCaseInsensitiveChecksForTest(this.otherUserName, test, expect);
removeSkipCaseInsensitiveChecksForTest(this.otherUsername, test, expect);
},
logoutStep,
// We shouldn't be able to log in with the email in lower case
@@ -378,7 +404,8 @@ if (Meteor.isClient) (function () {
}
]);
testAsyncMulti("passwords - creating users with the same case insensitive email", [
testAsyncMulti("passwords - creating users with the same case insensitive " +
"email", [
createUserStep,
logoutStep,
// Attempting to create another user with an email that only differs in
@@ -1229,7 +1256,8 @@ if (Meteor.isServer) (function () {
});
});
// XXX would be nice to test Accounts.config({forbidClientAccountCreation: true})
// XXX would be nice to test
// Accounts.config({forbidClientAccountCreation: true})
Tinytest.addAsync(
'passwords - login token observes get cleaned up',
@@ -1295,7 +1323,8 @@ if (Meteor.isServer) (function () {
Accounts.sendResetPasswordEmail(userId, email);
var resetPasswordEmailOptions = Meteor.call("getInterceptedEmails", email)[0];
var resetPasswordEmailOptions =
Meteor.call("getInterceptedEmails", email)[0];
var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)");
var match = resetPasswordEmailOptions.text.match(re);
@@ -1312,4 +1341,164 @@ if (Meteor.isServer) (function () {
Meteor.call("login", {user: {username: username}, password: "new-password"});
}, /Incorrect password/);
});
// We should be able to change the username
Tinytest.add("passwords - change username", function (test) {
var username = Random.id();
var userId = Accounts.createUser({
username: username
});
test.isTrue(userId);
var newUsername = Random.id();
Accounts.setUsername(userId, newUsername);
test.equal(Accounts._findUserByQuery({id: userId}).username, newUsername);
// Test findUserByUsername as well while we're here
test.equal(Accounts.findUserByUsername(newUsername)._id, userId);
});
Tinytest.add("passwords - change username to a new one only differing " +
"in case", function (test) {
var username = Random.id() + "user";
var userId = Accounts.createUser({
username: username.toUpperCase()
});
test.isTrue(userId);
var newUsername = username.toLowerCase();
Accounts.setUsername(userId, newUsername);
test.equal(Accounts._findUserByQuery({id: userId}).username, newUsername);
});
// We should not be able to change the username to one that only
// differs in case from an existing one
Tinytest.add("passwords - change username should fail when there are " +
"existing users with a username only differing in case", function (test) {
var username = Random.id() + "user";
var usernameUpper = username.toUpperCase();
var userId1 = Accounts.createUser({
username: username
});
var user2OriginalUsername = Random.id();
var userId2 = Accounts.createUser({
username: user2OriginalUsername
});
test.isTrue(userId1);
test.isTrue(userId2);
test.throws(function () {
Accounts.setUsername(userId2, usernameUpper);
}, /Username already exists/);
test.equal(Accounts._findUserByQuery({id: userId2}).username,
user2OriginalUsername);
});
Tinytest.add("passwords - add email", function (test) {
var origEmail = Random.id() + "@turing.com";
var userId = Accounts.createUser({
email: origEmail
});
var newEmail = Random.id() + "@turing.com";
Accounts.addEmail(userId, newEmail);
var thirdEmail = Random.id() + "@turing.com";
Accounts.addEmail(userId, thirdEmail, true);
test.equal(Accounts._findUserByQuery({id: userId}).emails, [
{ address: origEmail, verified: false },
{ address: newEmail, verified: false },
{ address: thirdEmail, verified: true }
]);
// Test findUserByEmail as well while we're here
test.equal(Accounts.findUserByEmail(origEmail)._id, userId);
});
Tinytest.add("passwords - add email when the user has an existing email " +
"only differing in case", function (test) {
var origEmail = Random.id() + "@turing.com";
var userId = Accounts.createUser({
email: origEmail
});
var newEmail = Random.id() + "@turing.com";
Accounts.addEmail(userId, newEmail);
var thirdEmail = origEmail.toUpperCase();
Accounts.addEmail(userId, thirdEmail, true);
test.equal(Accounts._findUserByQuery({id: userId}).emails, [
{ address: thirdEmail, verified: true },
{ address: newEmail, verified: false }
]);
});
Tinytest.add("passwords - add email should fail when there is an existing " +
"user with an email only differing in case", function (test) {
var user1Email = Random.id() + "@turing.com";
var userId1 = Accounts.createUser({
email: user1Email
});
var user2Email = Random.id() + "@turing.com";
var userId2 = Accounts.createUser({
email: user2Email
});
var dupEmail = user1Email.toUpperCase();
test.throws(function () {
Accounts.addEmail(userId2, dupEmail);
}, /Email already exists/);
test.equal(Accounts._findUserByQuery({id: userId1}).emails, [
{ address: user1Email, verified: false }
]);
test.equal(Accounts._findUserByQuery({id: userId2}).emails, [
{ address: user2Email, verified: false }
]);
});
Tinytest.add("passwords - remove email", function (test) {
var origEmail = Random.id() + "@turing.com";
var userId = Accounts.createUser({
email: origEmail
});
var newEmail = Random.id() + "@turing.com";
Accounts.addEmail(userId, newEmail);
var thirdEmail = Random.id() + "@turing.com";
Accounts.addEmail(userId, thirdEmail, true);
test.equal(Accounts._findUserByQuery({id: userId}).emails, [
{ address: origEmail, verified: false },
{ address: newEmail, verified: false },
{ address: thirdEmail, verified: true }
]);
Accounts.removeEmail(userId, newEmail);
test.equal(Accounts._findUserByQuery({id: userId}).emails, [
{ address: origEmail, verified: false },
{ address: thirdEmail, verified: true }
]);
Accounts.removeEmail(userId, origEmail);
test.equal(Accounts._findUserByQuery({id: userId}).emails, [
{ address: thirdEmail, verified: true }
]);
});
}) ();

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Twitter accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -146,13 +146,18 @@ Template._loginButtonsLoggedOutDropdown.events({
// force the ui to update so that we have the approprate fields to fill in
Tracker.flush();
if (document.getElementById('login-username'))
if (document.getElementById('login-username') && username !== null)
document.getElementById('login-username').value = username;
if (document.getElementById('login-email'))
if (document.getElementById('login-email') && email !== null)
document.getElementById('login-email').value = email;
if (document.getElementById('login-username-or-email'))
document.getElementById('login-username-or-email').value = email || username;
var usernameOrEmailInput = document.getElementById('login-username-or-email');
if (usernameOrEmailInput) {
if (email !== null)
usernameOrEmailInput.value = email;
if (username !== null)
usernameOrEmailInput.value = username;
}
if (password !== null)
document.getElementById('login-password').value = password;

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Unstyled version of login widgets",
version: "1.1.8-plugins.0"
version: "1.1.8"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Simple templates to add login widgets to an app",
version: "1.1.6-plugins.1"
version: "1.1.6"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Sina Weibo accounts",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Enable the application cache in the browser",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Try to detect inadequate input sanitization",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
// This package is empty; its presence is detected by livedata.

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "(For prototyping only) Publish the entire database to all clients",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
// This package is empty; its presence is detected by several other packages

View File

@@ -64,11 +64,11 @@ Undo previous changes made, such as by using `git checkout .` Reload
the client, which will cause the browser to stop using the app cache.
It's hard to see the `newClientAvailable` reactive variable when the
client automatically reloads. Remove the `reload` package so you can
client automatically reloads. Remove the `hot-code-push` package so you can
see the variable without having the client also reload.
$ meteor remove hot-code-push
$ meteor add autoupdate
$ meteor remove meteor-base
$ meteor add meteor webapp ddp autoupdate
Add to leaderboard.js:

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Update the client when new client code is available",
version: '1.2.2-plugins.1'
version: '1.2.3'
});
Cordova.depends({

View File

@@ -30,25 +30,22 @@
"asap": {
"version": "2.0.3"
},
"ast-types": {
"version": "0.8.5"
},
"ast-traverse": {
"version": "0.1.1"
},
"ast-types": {
"version": "0.8.5"
},
"async": {
"version": "0.2.10"
},
"babel-plugin-constant-folding": {
"version": "1.0.1"
},
"babel-plugin-eval": {
"version": "1.0.1"
},
"babel-plugin-dead-code-elimination": {
"version": "1.0.2"
},
"babel-plugin-inline-environment-variables": {
"babel-plugin-eval": {
"version": "1.0.1"
},
"babel-plugin-jscript": {
@@ -57,6 +54,9 @@
"babel-plugin-member-expression-literals": {
"version": "1.0.1"
},
"babel-plugin-inline-environment-variables": {
"version": "1.0.1"
},
"babel-plugin-property-literals": {
"version": "1.0.1"
},
@@ -66,12 +66,12 @@
"babel-plugin-react-constant-elements": {
"version": "1.0.3"
},
"babel-plugin-react-display-name": {
"version": "1.0.3"
},
"babel-plugin-remove-console": {
"version": "1.0.1"
},
"babel-plugin-react-display-name": {
"version": "1.0.3"
},
"babel-plugin-remove-debugger": {
"version": "1.0.1"
},
@@ -99,12 +99,12 @@
"breakable": {
"version": "1.0.0"
},
"camelcase": {
"version": "1.2.1"
},
"chalk": {
"version": "1.1.1"
},
"camelcase": {
"version": "1.2.1"
},
"character-parser": {
"version": "1.2.1"
},
@@ -132,24 +132,24 @@
"css-stringify": {
"version": "1.0.5"
},
"debug": {
"version": "2.2.0"
},
"decamelize": {
"version": "1.0.0"
},
"debug": {
"version": "2.2.0"
},
"detect-indent": {
"version": "3.0.1"
},
"diff": {
"version": "1.4.0"
},
"escape-string-regexp": {
"version": "1.0.3"
},
"esprima-fb": {
"version": "15001.1.0-dev-harmony-fb"
},
"escape-string-regexp": {
"version": "1.0.3"
},
"esutils": {
"version": "2.0.2"
},
@@ -159,12 +159,12 @@
"get-stdin": {
"version": "4.0.1"
},
"globals": {
"version": "6.4.1"
},
"graceful-fs": {
"version": "3.0.8"
},
"globals": {
"version": "6.4.1"
},
"graceful-readlink": {
"version": "1.0.1"
},
@@ -174,27 +174,27 @@
"has-ansi": {
"version": "2.0.0"
},
"home-or-tmp": {
"version": "1.0.0"
},
"iconv-lite": {
"version": "0.4.11"
},
"home-or-tmp": {
"version": "1.0.0"
},
"inflight": {
"version": "1.0.4"
},
"inherits": {
"version": "2.0.1"
},
"is-finite": {
"version": "1.0.1"
},
"install": {
"version": "0.1.8"
},
"is-integer": {
"version": "1.0.6"
},
"is-finite": {
"version": "1.0.1"
},
"is-promise": {
"version": "2.1.0"
},
@@ -219,24 +219,24 @@
"lodash": {
"version": "3.10.1"
},
"lru-cache": {
"version": "2.7.0"
},
"minimatch": {
"version": "2.0.10"
},
"lru-cache": {
"version": "2.7.0"
},
"minimist": {
"version": "1.2.0"
},
"ms": {
"version": "0.7.1"
},
"number-is-nan": {
"version": "1.0.0"
},
"once": {
"version": "1.3.2"
},
"number-is-nan": {
"version": "1.0.0"
},
"optimist": {
"version": "0.3.7"
},
@@ -285,12 +285,12 @@
"resolve": {
"version": "1.1.6"
},
"shebang-regex": {
"version": "1.0.0"
},
"sigmund": {
"version": "1.0.1"
},
"shebang-regex": {
"version": "1.0.0"
},
"simple-fmt": {
"version": "0.1.0"
},
@@ -306,12 +306,12 @@
"stable": {
"version": "0.1.5"
},
"stringmap": {
"version": "0.2.2"
},
"stringset": {
"version": "0.2.1"
},
"stringmap": {
"version": "0.2.2"
},
"strip-ansi": {
"version": "3.0.0"
},
@@ -373,14 +373,6 @@
}
}
},
"glob": {
"version": "4.2.2",
"dependencies": {
"minimatch": {
"version": "1.0.0"
}
}
},
"jade": {
"version": "1.11.0",
"dependencies": {
@@ -389,6 +381,14 @@
}
}
},
"glob": {
"version": "4.2.2",
"dependencies": {
"minimatch": {
"version": "1.0.0"
}
}
},
"jstransformer": {
"version": "0.0.2",
"dependencies": {

View File

@@ -3,7 +3,7 @@ Package.describe({
summary: "Parser/transpiler for ECMAScript 2015+ syntax",
// Tracks the npm version below. Use wrap numbers to increment
// without incrementing the npm version.
version: '5.8.24-plugins.0'
version: '5.8.24'
});
Npm.depends({

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Base64 encoding and decoding",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Binary Heap datastructure implementation",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'blaze-html-templates',
version: '1.0.0',
version: '1.0.1',
// Brief, one-line summary of the package.
summary: 'Compile HTML templates into reactive UI with Meteor Blaze',
// By default, Meteor will default to using README.md for documentation.

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Compile-time tools for Blaze",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
Package.onUse(function (api) {

View File

@@ -171,16 +171,15 @@ Blaze.Each = function (argFunc, contentFunc, elseFunc) {
}, {
addedAt: function (id, item, index) {
Tracker.nonreactive(function () {
var newDataContext;
var newItemView;
if (eachView.variableName) {
// new-style #each (as in {{#each item in items}})
// the new data context is the same
newDataContext = Blaze.getData(eachView);
// doesn't create a new data context
newItemView = Blaze.View('item', eachView.contentFunc);
} else {
newDataContext = item;
newItemView = Blaze.With(item, eachView.contentFunc);
}
var newItemView = Blaze.With(newDataContext, eachView.contentFunc);
eachView.numItems++;
var bindings = {};

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Meteor Reactive Templating library",
version: '2.1.3-plugins.0'
version: '2.1.3'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Generates the boilerplate html from program's manifest",
version: '1.0.4-plugins.0'
version: '1.0.4'
});
Package.onUse(function (api) {
@@ -12,7 +12,8 @@ Package.onUse(function (api) {
// spacebars compiler rather than letting the 'templating' package (which
// isn't fully supported on the server yet) handle it. That also means that
// they don't contain the outer "<template>" tag.
api.addFiles(['boilerplate_web.browser.html',
'boilerplate_web.cordova.html'],
'server', {isAsset: true});
api.addAssets([
'boilerplate_web.browser.html',
'boilerplate_web.cordova.html'
], 'server');
});

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Common code for browser-policy packages",
version: "1.0.4-plugins.0"
version: "1.0.4"
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Configure content security policies",
version: "1.0.5-plugins.0"
version: "1.0.5"
});
Package.onUse(function (api) {

Some files were not shown because too many files have changed in this diff Show More