diff --git a/History.md b/History.md index a0c56610be..c9303c3329 100644 --- a/History.md +++ b/History.md @@ -1,6 +1,84 @@ ## v.NEXT -* Allow query parameters in OAuth1 URLs. + +## v0.9.1 + +#### Organizations in Meteor developer accounts + +Meteor 0.9.1 ships with organizations support in Meteor developer +accounts. Organizations are teams of users that make it easy to +collaborate on apps and packages. + +Create an organization at +https://www.meteor.com/account-settings/organizations. Run the `meteor +authorized` command in your terminal to give an organization +permissions to your apps. To add an organization as a maintainer of +your packages, use the `meteor admin maintainers` command. You can +also publish packages with an organization's name in the package name +prefix instead of your own username. + + +#### One backwards incompatible change for templates + +* Templates can no longer be named "body" or "instance". + +#### Backwards compatible Blaze API changes + +* New public and documented APIs: + * `Blaze.toHTMLWithData()` + * `Template.currentData()` + * `Blaze.getView()` + * `Template.parentData()` (previously `UI._parentData()`) + * `Template.instance()` (previously `UI._templateInstance()`) + * `Template.body` (previously `UI.body`) + * `new Template` (previously `Template.__create__`) + * `Blaze.getData()` (previously `UI.getElementData`) + +* Deprecate the `ui` package. Instead, use the `blaze` package. The + `UI` and `Blaze` symbols are now the same. + +* Deprecate `UI.insert`. `UI.render` and `UI.renderWithData` now + render a template and place it in the DOM. + +* Add an underscore to some undocumented Blaze APIs to make them + internal. Notably: `Blaze._materializeView`, `Blaze._createView`, + `Blaze._toText`, `Blaze._destroyView`, `Blaze._destroyNode`, + `Blaze._withCurrentView`, `Blaze._DOMBackend`, + `Blaze._TemplateWith` + +* Document Views. Views are the machinery powering DOM updates in + Blaze. + +* Expose `view` property on template instances. + +#### Backwards compatible renames + +* Package renames + * `livedata` -> `ddp` + * `mongo-livedata` -> `mongo` + * `standard-app-packages` -> `meteor-platform` +* Symbol renames + * `Meteor.Collection` -> `Mongo.Collection` + * `Meteor.Collection.Cursor` -> `Mongo.Cursor` + * `Meteor.Collection.ObjectID` -> `Mongo.ObjectID` + * `Deps` -> `Tracker` + +#### Other + +* Add `reactive-var` package. Lets you define a single reactive + variable, like a single key in `Session`. + +* Don't throw an exception in Chrome when cookies and local storage + are blocked. + +* Bump DDP version to "1". Clients connecting with version "pre1" or + "pre2" should still work. + +* Allow query parameters in OAuth1 URLs. #2404 + +* Fix `meteor list` if not all packages on server. Fixes #2468 + +Patch by Github user mitar. ## v0.9.0.1 diff --git a/LICENSE.txt b/LICENSE.txt index 95014834ed..e1e55c2186 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2785,3 +2785,379 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +---------- +jsdoc: https://github.com/jsdoc3/jsdoc +---------- + +# License # + +JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the +"License"). Commercial and non-commercial use are permitted in compliance with +the License. + +Copyright (c) 2011-2014 Michael Mathews and the +[contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors). +All rights reserved. + +You may obtain a copy of the License at: +http://www.apache.org/licenses/LICENSE-2.0 + +In addition, a copy of the License is included with this distribution. + +As stated in Section 7, "Disclaimer of Warranty," of the License: + +> Licensor provides the Work (and each Contributor provides its Contributions) +> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +> express or implied, including, without limitation, any warranties or +> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +> PARTICULAR PURPOSE. You are solely responsible for determining the +> appropriateness of using or redistributing the Work and assume any risks +> associated with Your exercise of permissions under this License. + +The source code for JSDoc 3 is available at: +https://github.com/jsdoc3/jsdoc + +# Third-Party Software # + +JSDoc 3 includes or depends upon the following third-party software, either in +whole or in part. Each third-party software package is provided under its own +license. + +## MIT License ## + +Several of the following software packages are distributed under the MIT +license, which is reproduced below: + +> 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. + +## Acorn ## + +Portions of the Acorn source code are incorporated into the following files: + +- `lib/jsdoc/src/walker.js` + +Acorn is distributed under the MIT license, which is reproduced above. + +Copyright (C) 2012 Marijn Haverbeke . + +The source code for Acorn is available at: +https://github.com/marijnh/acorn + +## Async.js ## + +Async.js is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2010 Caolan McMahon. + +The source code for Async.js is available at: +https://github.com/caolan/async + +## Catharsis ## + +Catharsis is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2012-2014 Jeff Williams. + +The source code for Catharsis is available at: +https://github.com/hegemonic/catharsis + +## crypto-browserify ## + +crypto-browserify is distributed under the MIT license, which is reproduced +above. + +Copyright (c) 2013 Dominic Tarr. + +The source code for crypto-browserify is available at: +https://github.com/dominictarr/crypto-browserify + +## escape-string-regexp ## + +escape-string-regexp is distributed under the MIT License, which is reproduced +above. + +Copyright (c) Sindre Sorhus . + +The source code for escape-string-regexp is available at: +https://github.com/sindresorhus/escape-string-regexp + +## Esprima ## + +Esprima is distributed under the BSD 2-clause license: + +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions are met: +> +> - Redistributions of source code must retain the above copyright notice, +> this list of conditions and the following disclaimer. +> - Redistributions in binary form must reproduce the above copyright notice, +> this list of conditions and the following disclaimer in the documentation +> and/or other materials provided with the distribution. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +> ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +> DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +> (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +> ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +> THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (c) 2011-2013 Ariya Hidayat and other Esprima contributors. + +The source code for Esprima is available at: +https://github.com/ariya/esprima + +## events ## + +Portions of the events source code are incorporated into the following files: + ++ `rhino/events.js` + +events is distributed under the MIT license, which is reproduced above. + +Copyright Joyent, Inc. and other Node contributors. All rights reserved. + +The source code for events is available at: +https://github.com/Gozala/events + +## github-flavored-markdown ## + +github-flavored-markdown is distributed under the BSD 3-clause license: + +> Copyright (c) 2007, John Fraser All rights +> reserved. +> +> Original Markdown copyright (c) 2004, John Gruber +> All rights reserved. +> +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions are met: +> +> - Redistributions of source code must retain the above copyright notice, +> this list of conditions and the following disclaimer. +> +> - Redistributions in binary form must reproduce the above copyright notice, +> this list of conditions and the following disclaimer in the documentation +> and/or other materials provided with the distribution. + +> - Neither the name "Markdown" nor the names of its contributors may be used +> to endorse or promote products derived from this software without specific +> prior written permission. +> +> This software is provided by the copyright holders and contributors "as is" +> and any express or implied warranties, including, but not limited to, the +> implied warranties of merchantability and fitness for a particular purpose are +> disclaimed. In no event shall the copyright owner or contributors be liable +> for any direct, indirect, incidental, special, exemplary, or consequential +> damages (including, but not limited to, procurement of substitute goods or +> services; loss of use, data, or profits; or business interruption) however +> caused and on any theory of liability, whether in contract, strict liability, +> or tort (including negligence or otherwise) arising in any way out of the use +> of this software, even if advised of the possibility of such damage. + +The source code for github-flavored-markdown is available at: +https://github.com/hegemonic/github-flavored-markdown + +## Google Code Prettify ## + +Google Code Prettify is distributed under the Apache License 2.0, which is +included with this package. + +Copyright (c) 2006 Google Inc. + +The source code for Google Code Prettify is available at: +https://code.google.com/p/google-code-prettify/ + +## Jasmine ## + +Jasmine is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2008-2011 Pivotal Labs. + +The source code for Jasmine is available at: +https://github.com/pivotal/jasmine + +## jasmine-node ## + +jasmine-node is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2010 Adam Abrons and Misko Hevery (http://getangular.com). + +The source code for jasmine-node is available at: +https://github.com/mhevery/jasmine-node + +## js2xmlparser ## + +js2xmlparser is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2012 Michael Kourlas. + +The source code for js2xmlparser is available at: +https://github.com/michaelkourlas/node-js2xmlparser + +## Node.js ## + +Portions of the Node.js source code are incorporated into the following files: + +- `rhino/fs.js` +- `rhino/path.js` +- `rhino/querystring.js` +- `rhino/util.js` + +Node.js is distributed under the MIT license, which is reproduced above. + +Copyright Joyent, Inc. and other Node contributors. All rights reserved. + +The source code for Node.js is available at: +https://github.com/joyent/node + +## node-browser-builtins ## + +Portions of the node-browser-builtins source code are incorporated into the +following files: + +- `rhino/assert.js` +- `rhino/rhino-shim.js` + +node-browser-builtins is distributed under the MIT license, which is reproduced +above. + +The source code for node-browser-builtins is available at: +https://github.com/alexgorbatchev/node-browser-builtins + +## Requizzle ## + +Requizzle is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2014 Google Inc. All rights reserved. +Copyright (c) 2012-2013 Johannes Ewald. + +The source code for Requizzle is available at: +https://github.com/hegemonic/requizzle + +## Rhino ## + +Rhino is distributed under the following licenses: + +### MPL 2.0 License ### +The majority of the source code for Rhino is available under the Mozilla Public +License (MPL) 2.0, which is included in this distribution. + +### License for portions of the Rhino debugger ### +Additionally, some files are available under the BSD 3-clause license: + +> Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved. +> +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions are met: +> +> - Redistributions of source code must retain the above copyright notice, +> this list of conditions and the following disclaimer. +> - Redistributions in binary form must reproduce the above copyright +> notice, this list of conditions and the following disclaimer in the +> documentation and/or other materials provided with the distribution. +> - Neither the name of Sun Microsystems nor the names of its contributors +> may be used to endorse or promote products derived from this software +> without specific prior written permission. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +### Source Code ### +The source code for Rhino is available at: +https://github.com/jsdoc3/rhino + +## TaffyDB ## + +TaffyDB is distributed under a modified BSD license: + +> All rights reserved. +> +> Redistribution and use of this software in source and binary forms, with or +> without modification, are permitted provided that the following condition is +> met: +> +> Redistributions of source code must retain the above copyright notice, this +> list of conditions and the following disclaimer. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +> ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +> LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +> CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +> SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +> INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +> CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +> ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +> POSSIBILITY OF SUCH DAMAGE. + +The source code for TaffyDB is available at: +https://github.com/hegemonic/taffydb + +## Tomorrow Theme for Google Code Prettify ## + +License information for the Tomorrow Theme for Google Code Prettify is not +available. It is assumed that the package is distributed under an open source +license that is compatible with the Apache License 2.0. + +Copyright (c) Yoshihide Jimbo. + +The source code for the Tomorrow Theme is available at: +https://github.com/jmblog/color-themes-for-google-code-prettify + +## tv4 ## + +tv4 is in the public domain. It is also distributed under the MIT license, which +is reproduced above. + +The source code for tv4 is available at: +https://github.com/geraintluff/tv4 + +## Underscore.js ## + +Underscore.js is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative +Reporters & Editors. + +The source code for Underscore.js is available at: +https://github.com/jashkenas/underscore + +## wrench-js ## + +wrench-js is distributed under the MIT license, which is reproduced above. + +Copyright (c) 2010 Ryan McGrath. + +The source code for wrench-js is available at: +https://github.com/ryanmcgrath/wrench-js diff --git a/docs/.meteor/.finished-upgraders b/docs/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/docs/.meteor/.finished-upgraders +++ b/docs/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/docs/.meteor/release b/docs/.meteor/release index 8b309d9891..bc6b088311 100644 --- a/docs/.meteor/release +++ b/docs/.meteor/release @@ -1 +1 @@ -METEOR@0.9.1-rc2 +METEOR@0.9.1 diff --git a/docs/.meteor/versions b/docs/.meteor/versions index 20b0739bcd..b0aac67c44 100644 --- a/docs/.meteor/versions +++ b/docs/.meteor/versions @@ -1,18 +1,18 @@ appcache@1.0.0 -application-configuration@1.0.0 -autoupdate@1.0.6-rc0 +application-configuration@1.0.1 +autoupdate@1.0.6 binary-heap@1.0.0 blaze-tools@1.0.0 -blaze@2.0.0-rc0 +blaze@2.0.0 callback-hook@1.0.0 check@1.0.0 code-prettify@1.0.0 coffeescript@1.0.2 -ctl-helper@1.0.2 -ctl@1.0.0 -ddp@1.0.7 -ejson@1.0.1-rc0 -follower-livedata@1.0.0 +ctl-helper@1.0.3 +ctl@1.0.1 +ddp@1.0.8 +ejson@1.0.1 +follower-livedata@1.0.1 geojson-utils@1.0.0 html-tools@1.0.0 htmljs@1.0.0 @@ -20,29 +20,29 @@ id-map@1.0.0 jquery-waypoints@1.0.0 jquery@1.0.0 json@1.0.0 -less@1.0.7-rc0 +less@1.0.7 logging@1.0.2 -meteor-platform@1.0.1-rc0 -meteor@1.0.3-rc0 +meteor-platform@1.0.1 +meteor@1.0.3 minifiers@1.0.2 -minimongo@1.0.2-rc0 -mongo@1.0.3 -observe-sequence@1.0.2-rc0 +minimongo@1.0.2 +mongo@1.0.4 +observe-sequence@1.0.2 ordered-dict@1.0.0 random@1.0.0 -reactive-dict@1.0.1-rc0 -reactive-var@1.0.1-rc0 +reactive-dict@1.0.1 +reactive-var@1.0.1 reload-safetybelt@1.0.0 -reload@1.0.0 +reload@1.0.1 retry@1.0.0 routepolicy@1.0.0 -session@1.0.1-rc0 -showdown@1.0.1-rc0 -spacebars-compiler@1.0.2-rc0 -spacebars@1.0.1-rc0 -spiderable@1.0.3-rc0 -standard-app-packages@1.0.1-rc0 -templating@1.0.5-rc0 -tracker@1.0.2-rc1 +session@1.0.1 +showdown@1.0.1 +spacebars-compiler@1.0.2 +spacebars@1.0.1 +spiderable@1.0.3 +standard-app-packages@1.0.1 +templating@1.0.5 +tracker@1.0.2 underscore@1.0.0 -webapp@1.0.3-rc0 +webapp@1.0.3 diff --git a/docs/client/docs.js b/docs/client/docs.js index 00fcc5c0e3..82b65f30a9 100644 --- a/docs/client/docs.js +++ b/docs/client/docs.js @@ -1,5 +1,5 @@ Template.headline.release = function () { - return Meteor.release ? "0.9.1-rc2" : "(checkout)"; + return Meteor.release ? "0.9.1" : "(checkout)"; }; Meteor.startup(function () { diff --git a/docs/packages/application-configuration/.gitignore b/docs/packages/application-configuration/.gitignore new file mode 100644 index 0000000000..5e677eb9b5 --- /dev/null +++ b/docs/packages/application-configuration/.gitignore @@ -0,0 +1,2 @@ +.build +.build* diff --git a/docs/packages/application-configuration/config.js b/docs/packages/application-configuration/config.js new file mode 100644 index 0000000000..64b5f36091 --- /dev/null +++ b/docs/packages/application-configuration/config.js @@ -0,0 +1,200 @@ +var Future = Npm.require("fibers/future"); + +AppConfig = {}; + + +AppConfig.findGalaxy = _.once(function () { + if (!('GALAXY' in process.env || 'ULTRAWORLD_DDP_ENDPOINT' in process.env)) { + return null; + } + return Follower.connect(process.env.ULTRAWORLD_DDP_ENDPOINT || process.env.GALAXY); +}); + +var ultra = AppConfig.findGalaxy(); + +var subFuture = new Future(); +var subFutureJobs = new Future(); +if (ultra) { + ultra.subscribe("oneApp", process.env.GALAXY_APP, subFuture.resolver()); + ultra.subscribe("oneJob", process.env.GALAXY_JOB, subFutureJobs.resolver()); +} + +var Apps; +var Jobs; +var Services; +var collectionFuture = new Future(); + +Meteor.startup(function () { + var Mongo = Package.mongo.Mongo; + if (ultra) { + Apps = new Mongo.Collection("apps", { + connection: ultra + }); + Jobs = new Mongo.Collection("jobs", { + connection: ultra + }); + Services = new Mongo.Collection('services', { + connection: ultra + }); + // allow us to block on the collections being ready + collectionFuture.return(); + } +}); + +// XXX: Remove this once we allow the same collection to be new'd from multiple +// places. +AppConfig._getAppCollection = function () { + collectionFuture.wait(); + return Apps; +}; + +AppConfig._getJobsCollection = function () { + collectionFuture.wait(); + return Jobs; +}; + + +var staticAppConfig; + +try { + if (process.env.APP_CONFIG) { + staticAppConfig = JSON.parse(process.env.APP_CONFIG); + } else { + var settings; + try { + if (process.env.METEOR_SETTINGS) { + settings = JSON.parse(process.env.METEOR_SETTINGS); + } + } catch (e) { + Log.warn("Could not parse METEOR_SETTINGS as JSON"); + } + staticAppConfig = { + settings: settings, + packages: { + 'mongo-livedata': { + url: process.env.MONGO_URL, + oplog: process.env.MONGO_OPLOG_URL + } + } + }; + } +} catch (e) { + Log.warn("Could not parse initial APP_CONFIG environment variable"); +}; + +AppConfig.getAppConfig = function () { + if (!subFuture.isResolved() && staticAppConfig) { + return staticAppConfig; + } + subFuture.wait(); + var myApp = Apps.findOne(process.env.GALAXY_APP); + if (!myApp) { + throw new Error("there is no app config for this app"); + } + var config = myApp.config; + return config; +}; + +AppConfig.getStarForThisJob = function () { + if (ultra) { + subFutureJobs.wait(); + var job = Jobs.findOne(process.env.GALAXY_JOB); + if (job) { + return job.star; + } + } + return null; +}; + +AppConfig.configurePackage = function (packageName, configure) { + var appConfig = AppConfig.getAppConfig(); // Will either be based in the env var, + // or wait for galaxy to connect. + var lastConfig = + (appConfig && appConfig.packages && + appConfig.packages[packageName]) || {}; + + // Always call the configure callback "soon" even if the initial configuration + // is empty (synchronously, though deferred would be OK). + // XXX make sure that all callers of configurePackage deal well with multiple + // callback invocations! eg, email does not + configure(lastConfig); + var configureIfDifferent = function (app) { + if (!EJSON.equals( + app.config && app.config.packages && app.config.packages[packageName], + lastConfig)) { + lastConfig = app.config.packages[packageName]; + configure(lastConfig); + } + }; + var subHandle; + var observed = new Future(); + + // This is not required to finish, so defer it so it doesn't block anything + // else. + Meteor.defer( function () { + // there's a Meteor.startup() that produces the various collections, make + // sure it runs first before we continue. + collectionFuture.wait(); + subHandle = Apps.find(process.env.GALAXY_APP).observe({ + added: configureIfDifferent, + changed: configureIfDifferent + }); + observed.return(); + }); + + return { + stop: function () { + observed.wait(); + subHandle.stop(); + } + }; +}; + +AppConfig.configureService = function (serviceName, version, configure) { + + // Collect all the endpoints for this service, from both old- and new-format + // documents, and call the `configure` callback with all the service endpoints + // that we know about. + var callConfigure = function (doc) { + var serviceDocs = Services.find({ + name: serviceName, + version: version + }); + var endpoints = []; + serviceDocs.forEach(function (serviceDoc) { + if (serviceDoc.providers) { + _.each(serviceDoc.providers, function (endpoint, app) { + endpoints.push(endpoint); + }); + } else { + endpoints.push(serviceDoc.endpoint); + } + }); + configure(endpoints); + }; + + if (ultra) { + // there's a Meteor.startup() that produces the various collections, make + // sure it runs first before we continue. + collectionFuture.wait(); + // First try to subscribe to the new format service registrations; if that + // sub doesn't exist, then ultraworld hasn't updated to the new format yet, + // so try the old format `servicesByName` sub instead. + ultra.subscribe('services', serviceName, version, { + onError: function (err) { + if (err.error === 404) { + ultra.subscribe('servicesByName', serviceName); + } + } + }); + return Services.find({ + name: serviceName, + version: version + }).observe({ + added: callConfigure, + changed: callConfigure, + removed: callConfigure + }); + } + +}; diff --git a/docs/packages/application-configuration/package.js b/docs/packages/application-configuration/package.js new file mode 100644 index 0000000000..287590220e --- /dev/null +++ b/docs/packages/application-configuration/package.js @@ -0,0 +1,11 @@ +Package.describe({ + summary: "Interaction with the configuration sources for your apps", + version: '1.0.1' +}); + +Package.on_use(function (api) { + api.use(['logging', 'underscore', 'ddp', 'ejson', 'follower-livedata']); + api.use('mongo', {unordered: true}); + api.add_files(['config.js'], 'server'); + api.export('AppConfig', 'server'); +}); diff --git a/docs/packages/application-configuration/versions.json b/docs/packages/application-configuration/versions.json new file mode 100644 index 0000000000..c9a09f7c66 --- /dev/null +++ b/docs/packages/application-configuration/versions.json @@ -0,0 +1,71 @@ +{ + "dependencies": [ + [ + "callback-hook", + "1.0.0" + ], + [ + "check", + "1.0.0" + ], + [ + "ddp", + "1.0.8" + ], + [ + "ejson", + "1.0.1" + ], + [ + "follower-livedata", + "1.0.1" + ], + [ + "geojson-utils", + "1.0.0" + ], + [ + "id-map", + "1.0.0" + ], + [ + "json", + "1.0.0" + ], + [ + "logging", + "1.0.2" + ], + [ + "meteor", + "1.0.3" + ], + [ + "minimongo", + "1.0.2" + ], + [ + "ordered-dict", + "1.0.0" + ], + [ + "random", + "1.0.0" + ], + [ + "retry", + "1.0.0" + ], + [ + "tracker", + "1.0.2" + ], + [ + "underscore", + "1.0.0" + ] + ], + "pluginDependencies": [], + "toolVersion": "meteor-tool@1.0.27", + "format": "1.0" +} \ No newline at end of file diff --git a/examples/clock/.meteor/.finished-upgraders b/examples/clock/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/examples/clock/.meteor/.finished-upgraders +++ b/examples/clock/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/examples/clock/.meteor/release b/examples/clock/.meteor/release index cbef8b3e4d..bc6b088311 100644 --- a/examples/clock/.meteor/release +++ b/examples/clock/.meteor/release @@ -1 +1 @@ -METEOR@0.9.0.1 +METEOR@0.9.1 diff --git a/examples/clock/.meteor/versions b/examples/clock/.meteor/versions index e2a2bd0fb5..3065339240 100644 --- a/examples/clock/.meteor/versions +++ b/examples/clock/.meteor/versions @@ -1,16 +1,16 @@ -application-configuration@1.0.0 +application-configuration@1.0.1 autopublish@1.0.0 -autoupdate@1.0.5 +autoupdate@1.0.6 binary-heap@1.0.0 blaze-tools@1.0.0 -blaze@1.0.3 +blaze@2.0.0 callback-hook@1.0.0 check@1.0.0 -ctl-helper@1.0.2 -ctl@1.0.0 -deps@1.0.1 -ejson@1.0.0 -follower-livedata@1.0.0 +ctl-helper@1.0.3 +ctl@1.0.1 +ddp@1.0.8 +ejson@1.0.1 +follower-livedata@1.0.1 geojson-utils@1.0.0 html-tools@1.0.0 htmljs@1.0.0 @@ -18,24 +18,25 @@ id-map@1.0.0 insecure@1.0.0 jquery@1.0.0 json@1.0.0 -livedata@1.0.7 logging@1.0.2 -meteor@1.0.2 +meteor-platform@1.0.1 +meteor@1.0.3 minifiers@1.0.2 -minimongo@1.0.1 -mongo-livedata@1.0.3 -observe-sequence@1.0.1 +minimongo@1.0.2 +mongo@1.0.4 +observe-sequence@1.0.2 ordered-dict@1.0.0 random@1.0.0 -reactive-dict@1.0.0 -reload@1.0.0 +reactive-dict@1.0.1 +reactive-var@1.0.1 +reload@1.0.1 retry@1.0.0 routepolicy@1.0.0 -session@1.0.0 -spacebars-compiler@1.0.1 -spacebars@1.0.0 -standard-app-packages@1.0.0 -templating@1.0.4 -ui@1.0.0 +session@1.0.1 +spacebars-compiler@1.0.2 +spacebars@1.0.1 +standard-app-packages@1.0.1 +templating@1.0.5 +tracker@1.0.2 underscore@1.0.0 -webapp@1.0.2 +webapp@1.0.3 diff --git a/examples/leaderboard/.meteor/.finished-upgraders b/examples/leaderboard/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/examples/leaderboard/.meteor/.finished-upgraders +++ b/examples/leaderboard/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/examples/leaderboard/.meteor/release b/examples/leaderboard/.meteor/release index cbef8b3e4d..bc6b088311 100644 --- a/examples/leaderboard/.meteor/release +++ b/examples/leaderboard/.meteor/release @@ -1 +1 @@ -METEOR@0.9.0.1 +METEOR@0.9.1 diff --git a/examples/leaderboard/.meteor/versions b/examples/leaderboard/.meteor/versions index 4d8380af4b..94e90b2069 100644 --- a/examples/leaderboard/.meteor/versions +++ b/examples/leaderboard/.meteor/versions @@ -1,4 +1,4 @@ -application-configuration@1.0.0 +application-configuration@1.0.1 autopublish@1.0.0 autoupdate@1.0.7-cordova6 binary-heap@1.0.0 diff --git a/examples/parties/.meteor/.finished-upgraders b/examples/parties/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/examples/parties/.meteor/.finished-upgraders +++ b/examples/parties/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/examples/parties/.meteor/release b/examples/parties/.meteor/release index cbef8b3e4d..bc6b088311 100644 --- a/examples/parties/.meteor/release +++ b/examples/parties/.meteor/release @@ -1 +1 @@ -METEOR@0.9.0.1 +METEOR@0.9.1 diff --git a/examples/todos/.meteor/.finished-upgraders b/examples/todos/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/examples/todos/.meteor/.finished-upgraders +++ b/examples/todos/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/examples/todos/.meteor/release b/examples/todos/.meteor/release index cbef8b3e4d..bc6b088311 100644 --- a/examples/todos/.meteor/release +++ b/examples/todos/.meteor/release @@ -1 +1 @@ -METEOR@0.9.0.1 +METEOR@0.9.1 diff --git a/examples/todos/.meteor/versions b/examples/todos/.meteor/versions index 9d9e4d537e..465c988411 100644 --- a/examples/todos/.meteor/versions +++ b/examples/todos/.meteor/versions @@ -22,30 +22,26 @@ id-map@1.0.0 insecure@1.0.0 jquery@1.0.0 json@1.0.0 -logging@1.0.2-cordova2 -meteor-platform@1.1.0-rc0 -meteor@1.1.0-rc0 -minifiers@1.1.0-rc0 -minimongo@1.0.2-rc2 -mobile-status-bar@1.0.0-cordova2 -mongo@1.0.4-rc0 -observe-sequence@1.0.2-rc0 +logging@1.0.2 +meteor-platform@1.0.1 +meteor@1.0.3 +minifiers@1.0.2 +minimongo@1.0.2 +mongo@1.0.4 +observe-sequence@1.0.2 ordered-dict@1.0.0 random@1.0.0 -reactive-dict@1.0.1-rc1 -reactive-var@1.0.1-rc0 -reload@1.1.0-rc1 +reactive-dict@1.0.1 +reactive-var@1.0.1 +reload@1.0.1 retry@1.0.0 -routepolicy@1.0.0-cordova1 -session@1.0.1-rc0 -spacebars-compiler@1.0.2-rc0 -spacebars@1.0.1-rc1 -spiderable@1.0.3-rc0 -standard-app-packages@1.0.1-rc0 -templating@1.0.6-rc0 -tracker@1.0.2-rc1 -ui@1.0.1-rc0 +routepolicy@1.0.0 +session@1.0.1 +spacebars-compiler@1.0.2 +spacebars@1.0.1 +spiderable@1.0.3 +standard-app-packages@1.0.1 +templating@1.0.5 +tracker@1.0.2 underscore@1.0.0 -url@1.0.0-rc0 -webapp-hashing@1.0.0-cordova1 -webapp@1.1.0-rc1 +webapp@1.0.3 diff --git a/examples/wordplay/.meteor/.finished-upgraders b/examples/wordplay/.meteor/.finished-upgraders index 47bce205e9..ee0ed5a316 100644 --- a/examples/wordplay/.meteor/.finished-upgraders +++ b/examples/wordplay/.meteor/.finished-upgraders @@ -3,3 +3,4 @@ # with your project. notices-for-0.9.0 +notices-for-0.9.1 diff --git a/examples/wordplay/.meteor/release b/examples/wordplay/.meteor/release index cbef8b3e4d..bc6b088311 100644 --- a/examples/wordplay/.meteor/release +++ b/examples/wordplay/.meteor/release @@ -1 +1 @@ -METEOR@0.9.0.1 +METEOR@0.9.1 diff --git a/examples/wordplay/.meteor/versions b/examples/wordplay/.meteor/versions index 44e5ba94dd..e910b382f6 100644 --- a/examples/wordplay/.meteor/versions +++ b/examples/wordplay/.meteor/versions @@ -1,15 +1,15 @@ -application-configuration@1.0.0 -autoupdate@1.0.5 +application-configuration@1.0.1 +autoupdate@1.0.6 binary-heap@1.0.0 blaze-tools@1.0.0 -blaze@1.0.3 +blaze@2.0.0 callback-hook@1.0.0 check@1.0.0 -ctl-helper@1.0.2 -ctl@1.0.0 -deps@1.0.1 -ejson@1.0.0 -follower-livedata@1.0.0 +ctl-helper@1.0.3 +ctl@1.0.1 +ddp@1.0.8 +ejson@1.0.1 +follower-livedata@1.0.1 geojson-utils@1.0.0 html-tools@1.0.0 htmljs@1.0.0 @@ -17,24 +17,25 @@ id-map@1.0.0 insecure@1.0.0 jquery@1.0.0 json@1.0.0 -livedata@1.0.7 logging@1.0.2 -meteor@1.0.2 +meteor-platform@1.0.1 +meteor@1.0.3 minifiers@1.0.2 -minimongo@1.0.1 -mongo-livedata@1.0.3 -observe-sequence@1.0.1 +minimongo@1.0.2 +mongo@1.0.4 +observe-sequence@1.0.2 ordered-dict@1.0.0 random@1.0.0 -reactive-dict@1.0.0 -reload@1.0.0 +reactive-dict@1.0.1 +reactive-var@1.0.1 +reload@1.0.1 retry@1.0.0 routepolicy@1.0.0 -session@1.0.0 -spacebars-compiler@1.0.1 -spacebars@1.0.0 -standard-app-packages@1.0.0 -templating@1.0.4 -ui@1.0.0 +session@1.0.1 +spacebars-compiler@1.0.2 +spacebars@1.0.1 +standard-app-packages@1.0.1 +templating@1.0.5 +tracker@1.0.2 underscore@1.0.0 -webapp@1.0.2 +webapp@1.0.3 diff --git a/packages/accounts-password/package.js b/packages/accounts-password/package.js index c3e282bb09..e9932fadf6 100644 --- a/packages/accounts-password/package.js +++ b/packages/accounts-password/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Password support for accounts", - version: "1.0.1-rc1" + version: "1.0.1" }); Package.on_use(function(api) { diff --git a/packages/application-configuration/package.js b/packages/application-configuration/package.js index 57d808ecad..8fee67504f 100644 --- a/packages/application-configuration/package.js +++ b/packages/application-configuration/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Interaction with the configuration sources for your apps", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/blaze/package.js b/packages/blaze/package.js index 03eea2c4f6..8616206463 100644 --- a/packages/blaze/package.js +++ b/packages/blaze/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor Reactive Templating library", - version: '2.0.0-rc1' + version: '2.0.0' }); Package.on_use(function (api) { diff --git a/packages/bootstrap/package.js b/packages/bootstrap/package.js index 01401235c4..4b1c089ebb 100644 --- a/packages/bootstrap/package.js +++ b/packages/bootstrap/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Front-end framework from Twitter", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function (api) { diff --git a/packages/ctl-helper/package.js b/packages/ctl-helper/package.js index f61517289b..4c2a5f8237 100644 --- a/packages/ctl-helper/package.js +++ b/packages/ctl-helper/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Helpers for control programs", - version: "1.0.3-rc0" + version: "1.0.3" }); Npm.depends({optimist: '0.6.0'}); diff --git a/packages/ctl/package.js b/packages/ctl/package.js index 5c86fe71a9..8327b253a2 100644 --- a/packages/ctl/package.js +++ b/packages/ctl/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Default control program for an application", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function (api) { diff --git a/packages/ddp/package.js b/packages/ddp/package.js index 18be977b8e..9654cd10df 100644 --- a/packages/ddp/package.js +++ b/packages/ddp/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's latency-compensated distributed data framework", - version: '1.0.8-rc0' + version: '1.0.8' }); // We use 'faye-websocket' for connections in server-to-server DDP, mostly diff --git a/packages/deps/package.js b/packages/deps/package.js index b62928de3f..6c791bc494 100644 --- a/packages/deps/package.js +++ b/packages/deps/package.js @@ -2,7 +2,7 @@ Package.describe({ summary: "Deprecated package, please use tracker instead.", - version: '1.0.2-rc1' + version: '1.0.2' }); Package.on_use(function (api) { diff --git a/packages/ejson/package.js b/packages/ejson/package.js index fdf4ef8034..d1c15af0b2 100644 --- a/packages/ejson/package.js +++ b/packages/ejson/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Extended and Extensible JSON library", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/facts/package.js b/packages/facts/package.js index 5f02f7e579..1288ea21ee 100644 --- a/packages/facts/package.js +++ b/packages/facts/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Publish internal app statistics", - version: '1.0.1-rc1' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/follower-livedata/package.js b/packages/follower-livedata/package.js index 72c1e43670..fa76b74599 100644 --- a/packages/follower-livedata/package.js +++ b/packages/follower-livedata/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Maintain a connection to the leader of an election set", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/force-ssl/package.js b/packages/force-ssl/package.js index 7bc7a57b53..9a5f97c67e 100644 --- a/packages/force-ssl/package.js +++ b/packages/force-ssl/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Require this application to use HTTPS", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function (api) { diff --git a/packages/jquery-layout/package.js b/packages/jquery-layout/package.js index 6204f9aa03..6c4695fe80 100644 --- a/packages/jquery-layout/package.js +++ b/packages/jquery-layout/package.js @@ -3,7 +3,7 @@ Package.describe({ summary: "Easily create arbitrary multicolumn layouts", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function (api) { diff --git a/packages/livedata/package.js b/packages/livedata/package.js index 7f5c5844d7..dcb2ba7a54 100644 --- a/packages/livedata/package.js +++ b/packages/livedata/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Moved to the 'ddp' package", - version: '1.0.8-rc1' + version: '1.0.8' }); Package.on_use(function (api) { diff --git a/packages/mongo-livedata/package.js b/packages/mongo-livedata/package.js index c64b4c2d69..c252a62f38 100644 --- a/packages/mongo-livedata/package.js +++ b/packages/mongo-livedata/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Moved to the 'mongo' package", - version: '1.0.4-rc1' + version: '1.0.4' }); Package.on_use(function (api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index cd2910189b..e9656c8985 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.0.4-rc0' + version: '1.0.4' }); Npm.depends({ diff --git a/packages/observe-sequence/package.js b/packages/observe-sequence/package.js index d5035da9c7..183608db7f 100644 --- a/packages/observe-sequence/package.js +++ b/packages/observe-sequence/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Observe changes to various sequence types such as arrays, cursors and objects", - version: "1.0.2-rc0" + version: "1.0.2" }); Package.on_use(function (api) { diff --git a/packages/reactive-dict/package.js b/packages/reactive-dict/package.js index 8202cf18bb..773a1ca7ed 100644 --- a/packages/reactive-dict/package.js +++ b/packages/reactive-dict/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reactive dictionary", - version: '1.0.1-rc1' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/reactive-var/package.js b/packages/reactive-var/package.js index 44cc50e782..56ffd2b7b7 100644 --- a/packages/reactive-var/package.js +++ b/packages/reactive-var/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reactive variable", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/service-configuration/package.js b/packages/service-configuration/package.js index 5b95232cf5..c9e8cc23bf 100644 --- a/packages/service-configuration/package.js +++ b/packages/service-configuration/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Manage the configuration for third-party services", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function(api) { diff --git a/packages/session/package.js b/packages/session/package.js index cd8bac8b05..87c4687bce 100644 --- a/packages/session/package.js +++ b/packages/session/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Session variable", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/showdown/package.js b/packages/showdown/package.js index de3e2a8bf3..da96fed532 100644 --- a/packages/showdown/package.js +++ b/packages/showdown/package.js @@ -4,7 +4,7 @@ Package.describe({ summary: "Markdown-to-HTML processor", - version: "1.0.1-rc0" + version: "1.0.1" }); Package.on_use(function (api) { diff --git a/packages/spacebars-compiler/package.js b/packages/spacebars-compiler/package.js index 4b640386c0..bc863c5650 100644 --- a/packages/spacebars-compiler/package.js +++ b/packages/spacebars-compiler/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Compiler for Spacebars template language", - version: '1.0.2-rc0' + version: '1.0.2' }); Package.on_use(function (api) { diff --git a/packages/spacebars-tests/old_templates.js b/packages/spacebars-tests/old_templates.js new file mode 100644 index 0000000000..e92edcb877 --- /dev/null +++ b/packages/spacebars-tests/old_templates.js @@ -0,0 +1,2058 @@ +// This file contains templates compiled with a pre-0.9.0 version of +// spacebars-compiler. We run the entire suite of tests as we had on +// 0.9.0 against these compiled template. The test suits is found +// in old_templates_tests.js +// +// Why? Packages are published in built form. With Meteor 0.9.1, we +// didn't bump the major version of the 'templating' package (which +// would force packages that define templates to publish new versions +// of their package). Instead, we decided to keep backcompat with the +// old Blaze runtime APIs. +// +// If these tests ever break in the future, and backcompat is too hard +// to achieve (or undesirable), we can simply bump the major version +// of the 'templating' package, and get rid of these tests. +Template.__define__("old_spacebars_template_test_aaa", (function() { + var view = this; + return "aaa"; +})); + +Template.__define__("old_spacebars_template_test_bbb", (function() { + var view = this; + return "bbb"; +})); + +Template.__define__("old_spacebars_template_test_bracketed_this", (function() { + var view = this; + return [ "[", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "]" ]; +})); + +Template.__define__("old_spacebars_template_test_span_this", (function() { + var view = this; + return HTML.SPAN(Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + })); +})); + +Template.__define__("old_spacebars_template_test_content", (function() { + var view = this; + return Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateContentBlock); + }); + }); +})); + +Template.__define__("old_spacebars_template_test_elsecontent", (function() { + var view = this; + return Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateElseBlock); + }); + }); +})); + +Template.__define__("old_spacebars_template_test_iftemplate", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("condition")); + }, function() { + return [ "\n ", Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateContentBlock); + }); + }), "\n " ]; + }, function() { + return [ "\n ", Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateElseBlock); + }); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_simple_helper", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo"), view.lookup("bar")); + }); +})); + +Template.__define__("old_spacebars_template_test_dynamic_template", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("foo")); +})); + +Template.__define__("old_spacebars_template_test_interpolate_attribute", (function() { + var view = this; + return HTML.DIV({ + "class": function() { + return [ "aaa", Spacebars.mustache(view.lookup("foo"), view.lookup("bar")), "zzz" ]; + } + }); +})); + +Template.__define__("old_spacebars_template_test_dynamic_attrs", (function() { + var view = this; + return HTML.SPAN(HTML.Attrs(function() { + return Spacebars.attrMustache(view.lookup("attrsObj")); + }, function() { + return Spacebars.attrMustache(view.lookup("singleAttr")); + }, function() { + return Spacebars.attrMustache(view.lookup("nonexistent")); + }), "hi"); +})); + +Template.__define__("old_spacebars_template_test_triple", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("html"))); + }); +})); + +Template.__define__("old_spacebars_template_test_triple2", (function() { + var view = this; + return [ "x", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("html"))); + }), Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("html2"))); + }), Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("html3"))); + }), "y" ]; +})); + +Template.__define__("old_spacebars_template_test_inclusion_args", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.call(view.lookup("bar")); + }, function() { + return Spacebars.include(view.lookupTemplate("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_inclusion_args2", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.dataMustache(view.lookup("bar"), Spacebars.kw({ + q: view.lookup("baz") + })); + }, function() { + return Spacebars.include(view.lookupTemplate("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_inclusion_dotted_args", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.call(Spacebars.dot(view.lookup("bar"), "baz")); + }, function() { + return Spacebars.include(view.lookupTemplate("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_inclusion_slashed_args", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.call(Spacebars.dot(view.lookup("bar"), "baz")); + }, function() { + return Spacebars.include(view.lookupTemplate("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("foo"), function() { + return "\n bar\n "; + }, function() { + return "\n baz\n "; + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper_function_one_string_arg", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return "bar"; + }, function() { + return Spacebars.include(view.lookupTemplate("foo"), function() { + return "\n content\n "; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper_function_one_helper_arg", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.call(view.lookup("bar")); + }, function() { + return Spacebars.include(view.lookupTemplate("foo"), function() { + return "\n content\n "; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper_component_one_helper_arg", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("bar")); + }, function() { + return "\n content\n "; + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper_component_three_helper_args", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.dataMustache(view.lookup("equals"), view.lookup("bar_or_baz"), "bar"); + }, function() { + return "\n content\n "; + }); +})); + +Template.__define__("old_spacebars_template_test_block_helper_dotted_arg", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return Spacebars.dataMustache(Spacebars.dot(view.lookup("bar"), "baz"), view.lookup("qux")); + }, function() { + return Spacebars.include(view.lookupTemplate("foo"), function() { + return null; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_nested_content", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return { + condition: Spacebars.call(view.lookup("flag")) + }; + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_template_test_iftemplate"), function() { + return "\n hello\n "; + }, function() { + return "\n world\n "; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_iftemplate2", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return { + condition: Spacebars.call(view.lookup("flag")) + }; + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_template_test_iftemplate"), function() { + return [ "\n ", Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateContentBlock); + }); + }), "\n " ]; + }, function() { + return [ "\n ", Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateElseBlock); + }); + }), "\n " ]; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_nested_content2", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return { + flag: Spacebars.call(view.lookup("x")) + }; + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_template_test_iftemplate2"), function() { + return "\n hello\n "; + }, function() { + return "\n world\n "; + }); + }); +})); + +Template.__define__("old_spacebars_template_test_if", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), "\n " ]; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("baz")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_if_in_with", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), "\n ", Blaze.If(function() { + return true; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_each", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("text")); + }), "\n " ]; + }, function() { + return "\n else-clause\n "; + }); +})); + +Template.__define__("old_spacebars_template_test_dots", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n A\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("bar")); + }, function() { + return [ "\n B\n \n ", Blaze.If(function() { + return true; + }, function() { + return [ "\n C\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n D\n \n ", Spacebars.include(view.lookupTemplate("old_spacebars_template_test_dots_subtemplate")), "\n ", Spacebars.TemplateWith(function() { + return Spacebars.call(view.lookup("..")); + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_template_test_dots_subtemplate")); + }), "\n " ]; + }), "\n " ]; + }), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_dots_subtemplate", (function() { + var view = this; + return [ "TITLE\n 1", Blaze.View(function() { + return Spacebars.mustache(view.lookup("title")); + }), "\n 2", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("."), "title")); + }), "\n 3", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup(".."), "title")); + }), "\n 4", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("..."), "title")); + }), "\n\n GETTITLE\n 5", Blaze.View(function() { + return Spacebars.mustache(view.lookup("getTitle"), view.lookup(".")); + }), "\n 6", Blaze.View(function() { + return Spacebars.mustache(view.lookup("getTitle"), view.lookup("..")); + }), "\n 7", Blaze.View(function() { + return Spacebars.mustache(view.lookup("getTitle"), view.lookup("...")); + }) ]; +})); + +Template.__define__("old_spacebars_template_test_select_tag", (function() { + var view = this; + return HTML.SELECT("\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("optgroups")); + }, function() { + return [ "\n ", HTML.OPTGROUP({ + label: function() { + return Spacebars.mustache(view.lookup("label")); + } + }, "\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", HTML.OPTION(HTML.Attrs({ + value: function() { + return Spacebars.mustache(view.lookup("value")); + } + }, function() { + return Spacebars.attrMustache(view.lookup("selectedAttr")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("label")); + })), "\n " ]; + }), "\n "), "\n " ]; + }), "\n "); +})); + +Template.__define__("old_test_template_issue770", (function() { + var view = this; + return [ Spacebars.With(function() { + return Spacebars.call(view.lookup("value1")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }, function() { + return "\n xxx\n "; + }), "\n\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("value2")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }, function() { + return "\n xxx\n "; + }), "\n\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("value1")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }), "\n\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("value2")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }) ]; +})); + +Template.__define__("old_spacebars_template_test_tricky_attrs", (function() { + var view = this; + return [ HTML.INPUT({ + type: function() { + return Spacebars.mustache(view.lookup("theType")); + } + }), HTML.INPUT({ + type: "checkbox", + "class": function() { + return Spacebars.mustache(view.lookup("theClass")); + } + }) ]; +})); + +Template.__define__("old_spacebars_template_test_no_data", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("."), "foo")); + }), Blaze.Unless(function() { + return Spacebars.call(Spacebars.dot(view.lookup("."), "bar")); + }, function() { + return "asdf"; + }) ]; +})); + +Template.__define__("old_spacebars_template_test_textarea", (function() { + var view = this; + return HTML.TEXTAREA({ + value: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }); +})); + +Template.__define__("old_spacebars_template_test_textarea2", (function() { + var view = this; + return HTML.TEXTAREA({ + value: function() { + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return ""; + }, function() { + return ""; + }); + } + }); +})); + +Template.__define__("old_spacebars_template_test_textarea3", (function() { + var view = this; + return HTML.TEXTAREA({ + id: "myTextarea", + value: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }); +})); + +Template.__define__("old_spacebars_template_test_textarea_each", (function() { + var view = this; + return HTML.TEXTAREA({ + value: function() { + return Blaze.Each(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ ""; + }); + } + }); +})); + +Template.__define__("old_spacebars_template_test_defer_in_rendered", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_template_test_defer_in_rendered_subtemplate")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_defer_in_rendered_subtemplate", (function() { + var view = this; + return ""; +})); + +Template.__define__("old_spacebars_template_test_with_someData", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("someData")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), " ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_each_stops", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return "\n x\n "; + }); +})); + +Template.__define__("old_spacebars_template_test_block_helpers_in_attribute", (function() { + var view = this; + return HTML.DIV({ + "class": function() { + return Blaze.Each(function() { + return Spacebars.call(view.lookup("classes")); + }, function() { + return Blaze.If(function() { + return Spacebars.dataMustache(view.lookup("startsLowerCase"), view.lookup("name")); + }, function() { + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("name")); + }), " " ]; + }); + }, function() { + return "none"; + }); + } + }, "Smurf"); +})); + +Template.__define__("old_spacebars_template_test_block_helpers_in_attribute_2", (function() { + var view = this; + return HTML.INPUT({ + value: function() { + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return '"'; + }, function() { + return [ "&", HTML.CharRef({ + html: "<", + str: "<" + }), ">" ]; + }); + } + }); +})); + +Template.__define__("old_spacebars_template_test_constant_each_argument", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("someData")); + }, function() { + return [ "\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("anArray")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("justReturn"), view.lookup(".")); + }), "\n " ]; + }), "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_markdown_basic", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("obj")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("markdown"), function() { + return [ "\n", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n/each}}\n\n", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n/each}}\n\n* ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n* /each}}\n\n* ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n* /each}}\n\nsome paragraph to fix showdown's four space parsing below.\n\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n /each}}\n\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "\n /each}}\n\n>\n\n* >\n\n`>`\n\n >\n\n>\n\n* >\n\n`>`\n\n >\n\n`", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "`\n`/each}}`\n\n`", Blaze.View(function() { + return Spacebars.mustache(view.lookup("hi")); + }), "`\n`/each}}`\n\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_markdown_if", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("markdown"), function() { + return [ "\n\n", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\n", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\n* ", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\n* ", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\nsome paragraph to fix showdown's four space parsing below.\n\n ", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\n ", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "\n\n`", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "`\n\n`", Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return "true"; + }, function() { + return "false"; + }), "`\n\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_markdown_each", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("markdown"), function() { + return [ "\n\n", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\n", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\n* ", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\n* ", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\nsome paragraph to fix showdown's four space parsing below.\n\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "\n\n`", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "`\n\n`", Blaze.Each(function() { + return Spacebars.call(view.lookup("seq")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }), "`\n\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_markdown_inclusion", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("markdown"), function() { + return [ "\n", Spacebars.include(view.lookupTemplate("old_spacebars_template_test_markdown_inclusion_subtmpl")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_markdown_inclusion_subtmpl", (function() { + var view = this; + return HTML.SPAN(Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "Foo is ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), "." ]; + })); +})); + +Template.__define__("old_spacebars_template_test_markdown_block_helpers", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("markdown"), function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_template_test_just_content"), function() { + return "\nHi there!\n "; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_just_content", (function() { + var view = this; + return Blaze.InOuterTemplateScope(view, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateContentBlock); + }); + }); +})); + +Template.__define__("old_spacebars_template_test_simple_helpers_are_isolated", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_attr_helpers_are_isolated", (function() { + var view = this; + return HTML.P({ + attr: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }); +})); + +Template.__define__("old_spacebars_template_test_attr_object_helpers_are_isolated", (function() { + var view = this; + return HTML.P(HTML.Attrs(function() { + return Spacebars.attrMustache(view.lookup("attrs")); + })); +})); + +Template.__define__("old_spacebars_template_test_inclusion_helpers_are_isolated", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("foo")); +})); + +Template.__define__("old_spacebars_template_test_inclusion_helpers_are_isolated_subtemplate", (function() { + var view = this; + return ""; +})); + +Template.__define__("old_spacebars_template_test_nully_attributes0", (function() { + var view = this; + return HTML.Raw(''); +})); + +Template.__define__("old_spacebars_template_test_nully_attributes1", (function() { + var view = this; + return HTML.INPUT({ + type: "checkbox", + checked: function() { + return Spacebars.mustache(view.lookup("foo")); + }, + stuff: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }); +})); + +Template.__define__("old_spacebars_template_test_nully_attributes2", (function() { + var view = this; + return HTML.INPUT({ + type: "checkbox", + checked: function() { + return [ Spacebars.mustache(view.lookup("foo")), Spacebars.mustache(view.lookup("bar")) ]; + }, + stuff: function() { + return [ Spacebars.mustache(view.lookup("foo")), Spacebars.mustache(view.lookup("bar")) ]; + } + }); +})); + +Template.__define__("old_spacebars_template_test_nully_attributes3", (function() { + var view = this; + return HTML.INPUT({ + type: "checkbox", + checked: function() { + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return null; + }); + }, + stuff: function() { + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return null; + }); + } + }); +})); + +Template.__define__("old_spacebars_template_test_double", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }); +})); + +Template.__define__("old_spacebars_template_test_inclusion_lookup", (function() { + var view = this; + return [ Spacebars.include(view.lookupTemplate("old_spacebars_template_test_inclusion_lookup_subtmpl")), "\n ", Spacebars.include(view.lookupTemplate("dataContextSubtmpl")) ]; +})); + +Template.__define__("old_spacebars_template_test_inclusion_lookup_subtmpl", (function() { + var view = this; + return "This is the template."; +})); + +Template.__define__("old_spacebars_template_test_inclusion_lookup_subtmpl2", (function() { + var view = this; + return "This is generated by a helper with the same name."; +})); + +Template.__define__("old_spacebars_template_test_inclusion_lookup_subtmpl3", (function() { + var view = this; + return "This is a template passed in the data context."; +})); + +Template.__define__("old_spacebars_template_test_content_context", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("bar")); + }, function() { + return [ "\n ", Spacebars.TemplateWith(function() { + return { + condition: Spacebars.call(view.lookup("cond")) + }; + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_template_test_iftemplate"), function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("firstLetter")); + }), Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup(".."), "secondLetter")); + }), "\n " ]; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup(".."), "firstLetter")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("secondLetter")); + }), "\n " ]; + }); + }), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_control_input", (function() { + var view = this; + return HTML.INPUT({ + type: function() { + return Spacebars.mustache(view.lookup("type")); + }, + value: function() { + return Spacebars.mustache(view.lookup("value")); + } + }); +})); + +Template.__define__("old_spacebars_test_control_textarea", (function() { + var view = this; + return HTML.TEXTAREA({ + value: function() { + return Spacebars.mustache(view.lookup("value")); + } + }); +})); + +Template.__define__("old_spacebars_test_control_select", (function() { + var view = this; + return HTML.SELECT("\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", HTML.OPTION({ + selected: function() { + return Spacebars.mustache(view.lookup("selected")); + } + }, Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + })), "\n " ]; + }), "\n "); +})); + +Template.__define__("old_spacebars_test_control_radio", (function() { + var view = this; + return [ "Band:\n\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("bands")); + }, function() { + return [ "\n ", HTML.INPUT({ + name: "bands", + type: "radio", + value: function() { + return Spacebars.mustache(view.lookup(".")); + }, + checked: function() { + return Spacebars.mustache(view.lookup("isChecked")); + } + }), "\n " ]; + }), "\n\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("band")); + }) ]; +})); + +Template.__define__("old_spacebars_test_control_checkbox", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("labels")); + }, function() { + return [ "\n ", HTML.INPUT({ + type: "checkbox", + value: function() { + return Spacebars.mustache(view.lookup(".")); + }, + checked: function() { + return Spacebars.mustache(view.lookup("isChecked")); + } + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_nonexistent_template", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("this_template_lives_in_outer_space")); +})); + +Template.__define__("old_spacebars_test_if_helper", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return "\n true\n "; + }, function() { + return "\n false\n "; + }); +})); + +Template.__define__("old_spacebars_test_block_helper_function", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("foo"), function() { + return "\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_onetwo", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("showOne")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("one")), "\n " ]; + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("two")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_onetwo_attribute", (function() { + var view = this; + return HTML.BR({ + "data-stuff": function() { + return Blaze.If(function() { + return Spacebars.call(view.lookup("showOne")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("one")), "\n " ]; + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("two")), "\n " ]; + }); + } + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with1", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n one\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with2", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n two\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_each1", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n one\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_each2", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n two\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_each1", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_helpers_stop_with_each3")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_each2", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_helpers_stop_with_each3")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_each3", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup(".")); + }, function() { + return "\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_if1", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n one\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_if2", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n two\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_inclusion1", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("options")); +})); + +Template.__define__("old_spacebars_test_helpers_stop_inclusion2", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("options")); +})); + +Template.__define__("old_spacebars_test_helpers_stop_inclusion3", (function() { + var view = this; + return "blah"; +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_callbacks1", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_helpers_stop_with_callbacks3")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_callbacks2", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_helpers_stop_with_callbacks3")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_with_callbacks3", (function() { + var view = this; + return "blah"; +})); + +Template.__define__("old_spacebars_test_helpers_stop_unless1", (function() { + var view = this; + return Blaze.Unless(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n one\n "; + }); +})); + +Template.__define__("old_spacebars_test_helpers_stop_unless2", (function() { + var view = this; + return Blaze.Unless(function() { + return Spacebars.call(view.lookup("options")); + }, function() { + return "\n two\n "; + }); +})); + +Template.__define__("old_spacebars_test_no_data_context", (function() { + var view = this; + return [ HTML.Raw("\n "), Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }) ]; +})); + +Template.__define__("old_spacebars_test_falsy_with", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("obj")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("greekLetter")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_helpers_dont_leak", (function() { + var view = this; + return Spacebars.TemplateWith(function() { + return { + foo: Spacebars.call("correct") + }; + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_test_helpers_dont_leak2")); + }); +})); + +Template.__define__("old_spacebars_test_helpers_dont_leak2", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), " ", Spacebars.include(view.lookupTemplate("old_spacebars_template_test_content"), function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("bonus")); + }); + }) ]; +})); + +Template.__define__("old_spacebars_test_event_returns_false", (function() { + var view = this; + return HTML.Raw('click me'); +})); + +Template.__define__("old_spacebars_test_event_selectors1", (function() { + var view = this; + return HTML.DIV(Spacebars.include(view.lookupTemplate("old_spacebars_test_event_selectors2"))); +})); + +Template.__define__("old_spacebars_test_event_selectors2", (function() { + var view = this; + return HTML.Raw('

Not it

\n

It

'); +})); + +Template.__define__("old_spacebars_test_event_selectors_capturing1", (function() { + var view = this; + return HTML.DIV(Spacebars.include(view.lookupTemplate("old_spacebars_test_event_selectors_capturing2"))); +})); + +Template.__define__("old_spacebars_test_event_selectors_capturing2", (function() { + var view = this; + return HTML.Raw('\n
\n \n
'); +})); + +Template.__define__("old_spacebars_test_tables1", (function() { + var view = this; + return HTML.TABLE(HTML.TR(HTML.TD("Foo"))); +})); + +Template.__define__("old_spacebars_test_tables2", (function() { + var view = this; + return HTML.TABLE(HTML.TR(HTML.TD(Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + })))); +})); + +Template.__define__("old_spacebars_test_jquery_events", (function() { + var view = this; + return HTML.Raw(''); +})); + +Template.__define__("old_spacebars_test_tohtml_basic", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }); +})); + +Template.__define__("old_spacebars_test_tohtml_if", (function() { + var view = this; + return Blaze.If(function() { + return true; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_tohtml_with", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_tohtml_each", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("foos")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_tohtml_include_with", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("old_spacebars_test_tohtml_with")); +})); + +Template.__define__("old_spacebars_test_tohtml_include_each", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("old_spacebars_test_tohtml_each")); +})); + +Template.__define__("old_spacebars_test_block_comment", (function() { + var view = this; + return "\n "; +})); + +Template.__define__("old_spacebars_test_with_mutated_data_context", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("value")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_url_attribute", (function() { + var view = this; + return [ HTML.A({ + href: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }), "\n ", HTML.A({ + href: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }), "\n ", HTML.FORM({ + action: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }), "\n ", HTML.IMG({ + src: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }), "\n ", HTML.INPUT({ + value: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }) ]; +})); + +Template.__define__("old_spacebars_test_event_handler_cleanup", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_event_handler_cleanup_sub")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_event_handler_cleanup_sub", (function() { + var view = this; + return HTML.Raw("
"); +})); + +Template.__define__("old_spacebars_test_data_context_for_event_handler_in_if", (function() { + var view = this; + return Spacebars.With(function() { + return { + foo: Spacebars.call("bar") + }; + }, function() { + return [ "\n ", Blaze.If(function() { + return true; + }, function() { + return [ "\n ", HTML.SPAN("Click me!"), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_each_with_autorun_insert", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("name")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_ui_hooks", (function() { + var view = this; + return HTML.DIV({ + "class": "test-ui-hooks" + }, "\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n ", HTML.DIV({ + "class": "item" + }, Blaze.View(function() { + return Spacebars.mustache(view.lookup("_id")); + })), "\n " ]; + }), "\n "); +})); + +Template.__define__("old_spacebars_test_ui_hooks_nested", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_ui_hooks_nested_sub")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_ui_hooks_nested_sub", (function() { + var view = this; + return HTML.DIV("\n ", Spacebars.With(function() { + return true; + }, function() { + return [ "\n ", HTML.P("hello"), "\n " ]; + }), "\n "); +})); + +Template.__define__("old_spacebars_test_template_instance_helper", (function() { + var view = this; + return Spacebars.With(function() { + return true; + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }); + }); +})); + +Template.__define__("old_spacebars_test_with_cleanup", (function() { + var view = this; + return HTML.DIV({ + "class": "test-with-cleanup" + }, "\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }), "\n " ]; + }), "\n "); +})); + +Template.__define__("old_spacebars_test_template_parent_data_helper", (function() { + var view = this; + return Spacebars.With(function() { + return "parent"; + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_template_parent_data_helper_child")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_template_parent_data_helper_child", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("a")); + }, function() { + return [ "\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("b")); + }, function() { + return [ "\n ", Blaze.If(function() { + return Spacebars.call(view.lookup("c")); + }, function() { + return [ "\n ", Spacebars.With(function() { + return "d"; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), "\n " ]; + }), "\n " ]; + }), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_svg_anchor", (function() { + var view = this; + return HTML.SVG("\n ", HTML.A({ + "xlink:href": "http://www.example.com" + }, "Foo"), "\n "); +})); + +Template.__define__("old_spacebars_test_template_created_rendered_destroyed_each", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("items")); + }, function() { + return [ "\n ", HTML.DIV(Spacebars.TemplateWith(function() { + return Spacebars.call(view.lookup("_id")); + }, function() { + return Spacebars.include(view.lookupTemplate("old_spacebars_test_template_created_rendered_destroyed_each_sub")); + })), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_template_created_rendered_destroyed_each_sub", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); +})); + +Template.__define__("old_spacebars_test_ui_getElementData", (function() { + var view = this; + return HTML.Raw(""); +})); + +Template.__define__("old_spacebars_test_ui_render", (function() { + var view = this; + return HTML.SPAN(Blaze.View(function() { + return Spacebars.mustache(view.lookup("greeting")); + }), " ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("r")); + })); +})); + +Template.__define__("old_spacebars_test_parent_removal", (function() { + var view = this; + return HTML.DIV({ + "class": "a" + }, "\n ", HTML.DIV({ + "class": "b" + }, "\n ", HTML.DIV({ + "class": "toremove" + }, "\n ", HTML.DIV({ + "class": "c" + }, "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), 1); + }), "\n ", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("A"), 2)); + }), "\n ", Spacebars.With(function() { + return Spacebars.dataMustache(view.lookup("A"), 3); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), 4); + }), "\n ", Spacebars.With(function() { + return Spacebars.dataMustache(view.lookup("A"), 5); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), 6); + }), "\n " ]; + }), "\n " ]; + }), "\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("B")); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), 7); + }), "\n " ]; + }), "\n ", Blaze.If(function() { + return Spacebars.dataMustache(view.lookup("A"), 8); + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), 9); + }), "\n " ]; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("A"), "a"); + }), "\n " ]; + }), "\n "), "\n "), "\n "), "\n "); +})); + +Template.__define__("old_spacebars_test_focus_blur_outer", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return [ "\n a ", Spacebars.include(view.lookupTemplate("old_spacebars_test_focus_blur_inner")), "\n " ]; + }, function() { + return [ "\n b ", Spacebars.include(view.lookupTemplate("old_spacebars_test_focus_blur_inner")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_focus_blur_inner", (function() { + var view = this; + return HTML.Raw(''); +})); + +Template.__define__("old_spacebars_test_event_cleanup_on_destroyed_outer", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("cond")); + }, function() { + return [ "\n ", HTML.DIV("a ", Spacebars.include(view.lookupTemplate("old_spacebars_test_event_cleanup_on_destroyed_inner"))), "\n " ]; + }, function() { + return [ "\n ", HTML.DIV("b ", Spacebars.include(view.lookupTemplate("old_spacebars_test_event_cleanup_on_destroyed_inner"))), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_event_cleanup_on_destroyed_inner", (function() { + var view = this; + return HTML.Raw("foo"); +})); + +Template.__define__("old_spacebars_test_isolated_lookup_inclusion", (function() { + var view = this; + return "x"; +})); + +Template.__define__("old_spacebars_test_isolated_lookup1", (function() { + var view = this; + return [ Spacebars.include(view.lookupTemplate("foo")), "--", Spacebars.include(view.lookupTemplate("old_spacebars_test_isolated_lookup_inclusion")) ]; +})); + +Template.__define__("old_spacebars_test_isolated_lookup2", (function() { + var view = this; + return Spacebars.With(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", Spacebars.With(function() { + return { + z: Spacebars.call(1) + }; + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("..")), "--", Spacebars.include(view.lookupTemplate("old_spacebars_test_isolated_lookup_inclusion")), "\n " ]; + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_isolated_lookup3", (function() { + var view = this; + return [ Spacebars.include(view.lookupTemplate("bar")), "--", Spacebars.include(view.lookupTemplate("old_spacebars_test_isolated_lookup_inclusion")) ]; +})); + +Template.__define__("old_spacebars_test_current_view_in_event", (function() { + var view = this; + return HTML.SPAN(Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + })); +})); + +Template.__define__("old_spacebars_test_textarea_attrs", (function() { + var view = this; + return HTML.TEXTAREA(HTML.Attrs(function() { + return Spacebars.attrMustache(view.lookup("attrs")); + })); +})); + +Template.__define__("old_spacebars_test_textarea_attrs_contents", (function() { + var view = this; + return HTML.TEXTAREA(HTML.Attrs(function() { + return Spacebars.attrMustache(view.lookup("attrs")); + }, { + value: function() { + return [ "Hello ", Spacebars.mustache(view.lookup("name")) ]; + } + })); +})); + +Template.__define__("old_spacebars_test_textarea_attrs_array_contents", (function() { + var view = this; + return HTML.TEXTAREA(HTML.Attrs({ + "class": "bar" + }, function() { + return Spacebars.attrMustache(view.lookup("attrs")); + }, { + value: function() { + return [ "Hello ", Spacebars.mustache(view.lookup("name")) ]; + } + })); +})); + +Template.__define__("old_spacebars_test_autorun", (function() { + var view = this; + return Blaze.If(function() { + return Spacebars.call(view.lookup("show")); + }, function() { + return [ "\n ", Spacebars.include(view.lookupTemplate("old_spacebars_test_autorun_inner")), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_autorun_inner", (function() { + var view = this; + return "Hello"; +})); + +Template.__define__("old_spacebars_test_contentBlock_arg", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("old_spacebars_test_contentBlock_arg_inner"), function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("."), "bar")); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_test_contentBlock_arg_inner", (function() { + var view = this; + return Spacebars.With(function() { + return { + foo: Spacebars.call("AAA"), + bar: Spacebars.call("BBB") + }; + }, function() { + return [ "\n ", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("."), "foo")); + }), " ", Blaze.InOuterTemplateScope(view, function() { + return Spacebars.TemplateWith(function() { + return Spacebars.call(view.lookup(".")); + }, function() { + return Spacebars.include(function() { + return Spacebars.call(view.templateContentBlock); + }); + }); + }), "\n " ]; + }); +})); + +Template.__define__("old_spacebars_template_test_input_field_to_same_value", (function() { + var view = this; + return HTML.INPUT({ + type: "text", + value: function() { + return Spacebars.mustache(view.lookup("foo")); + } + }); +})); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +Template.__define__("old_test_assembly_a0", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("test_assembly_a1")); +})); + +Template.__define__("old_test_assembly_a1", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("test_assembly_a2")); +})); + +Template.__define__("old_test_assembly_a2", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("test_assembly_a3")); +})); + +Template.__define__("old_test_assembly_a3", (function() { + var view = this; + return "Hi"; +})); + +Template.__define__("old_test_assembly_b0", (function() { + var view = this; + return Spacebars.include(view.lookupTemplate("test_assembly_b1")); +})); + +Template.__define__("old_test_assembly_b1", (function() { + var view = this; + return [ "x", Blaze.If(function() { + return Spacebars.call(view.lookup("stuff")); + }, function() { + return "y"; + }), Spacebars.include(view.lookupTemplate("test_assembly_b2")) ]; +})); + +Template.__define__("old_test_assembly_b2", (function() { + var view = this; + return "hi"; +})); + +Template.__define__("old_test_table_b0", (function() { + var view = this; + return HTML.TABLE("\n ", HTML.TBODY("\n ", Spacebars.include(view.lookupTemplate("test_table_b1")), "\n ", Spacebars.include(view.lookupTemplate("test_table_b1")), "\n ", Spacebars.include(view.lookupTemplate("test_table_b1")), "\n "), "\n "); +})); + +Template.__define__("old_test_table_b1", (function() { + var view = this; + return HTML.TR("\n ", Spacebars.include(view.lookupTemplate("test_table_b2")), "\n "); +})); + +Template.__define__("old_test_table_b2", (function() { + var view = this; + return HTML.TD("\n ", Spacebars.include(view.lookupTemplate("test_table_b3")), "\n "); +})); + +Template.__define__("old_test_table_b3", (function() { + var view = this; + return "Foo."; +})); + +Template.__define__("old_test_table_each", (function() { + var view = this; + return HTML.TABLE("\n ", HTML.TBODY("\n ", Blaze.Each(function() { + return Spacebars.call(view.lookup("foo")); + }, function() { + return [ "\n ", HTML.TR(HTML.TD(Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }))), "\n " ]; + }), "\n "), "\n "); +})); + +Template.__define__("old_test_event_data_with", (function() { + var view = this; + return HTML.DIV("\n xxx\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("TWO")); + }, function() { + return [ "\n ", HTML.DIV("\n xxx\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("THREE")); + }, function() { + return [ "\n ", HTML.DIV("\n xxx\n "), "\n " ]; + }), "\n "), "\n " ]; + }), "\n"); +})); + +Template.__define__("old_test_capture_events", (function() { + var view = this; + return HTML.Raw('\n \n '); +})); + +Template.__define__("old_test_safestring_a", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), " ", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("foo"))); + }), " ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), " ", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("bar"))); + }), "\n ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("fooprop")); + }), " ", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("fooprop"))); + }), " ", Blaze.View(function() { + return Spacebars.mustache(view.lookup("barprop")); + }), " ", Blaze.View(function() { + return Spacebars.makeRaw(Spacebars.mustache(view.lookup("barprop"))); + }) ]; +})); + +Template.__define__("old_test_helpers_a", (function() { + var view = this; + return [ "platypus=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("platypus")); + }), "\n watermelon=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("watermelon")); + }), "\n daisy=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("daisy")); + }), "\n tree=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("tree")); + }), "\n warthog=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("warthog")); + }) ]; +})); + +Template.__define__("old_test_helpers_b", (function() { + var view = this; + return [ "unknown=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("unknown")); + }), "\n zero=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("zero")); + }) ]; +})); + +Template.__define__("old_test_helpers_c", (function() { + var view = this; + return [ "platypus.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("platypus"), "X")); + }), "\n watermelon.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("watermelon"), "X")); + }), "\n daisy.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("daisy"), "X")); + }), "\n tree.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("tree"), "X")); + }), "\n warthog.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("warthog"), "X")); + }), "\n getNull.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("getNull"), "X")); + }), "\n getUndefined.X=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("getUndefined"), "X")); + }), "\n getUndefined.X.Y=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("getUndefined"), "X", "Y")); + }) ]; +})); + +Template.__define__("old_test_helpers_d", (function() { + var view = this; + return [ "daisygetter=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("daisygetter")); + }), "\n thisTest=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("thisTest")); + }), "\n ", Spacebars.With(function() { + return Spacebars.call(view.lookup("fancy")); + }, function() { + return [ "\n ../thisTest=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup(".."), "thisTest")); + }), "\n " ]; + }), "\n ", Spacebars.With(function() { + return "foo"; + }, function() { + return [ "\n ../fancy.currentFruit=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup(".."), "fancy", "currentFruit")); + }), "\n " ]; + }) ]; +})); + +Template.__define__("old_test_helpers_e", (function() { + var view = this; + return [ "fancy.foo=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "foo")); + }), "\n fancy.apple.banana=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "apple", "banana")); + }), "\n fancy.currentFruit=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "currentFruit")); + }), "\n fancy.currentCountry.name=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "currentCountry", "name")); + }), "\n fancy.currentCountry.population=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "currentCountry", "population")); + }), "\n fancy.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancy"), "currentCountry", "unicorns")); + }) ]; +})); + +Template.__define__("old_test_helpers_f", (function() { + var view = this; + return [ "fancyhelper.foo=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "foo")); + }), "\n fancyhelper.apple.banana=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "apple", "banana")); + }), "\n fancyhelper.currentFruit=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "currentFruit")); + }), "\n fancyhelper.currentCountry.name=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "name")); + }), "\n fancyhelper.currentCountry.population=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "population")); + }), "\n fancyhelper.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns")); + }) ]; +})); + +Template.__define__("old_test_helpers_g", (function() { + var view = this; + return [ "platypus=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("platypus")); + }), "\n this.platypus=", Blaze.View(function() { + return Spacebars.mustache(Spacebars.dot(view.lookup("."), "platypus")); + }) ]; +})); + +Template.__define__("old_test_helpers_h", (function() { + var view = this; + return [ "(methodListFour 6 7 8 9=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("methodListFour"), 6, 7, 8, 9); + }), ")\n (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("methodListFour"), view.lookup("platypus"), view.lookup("thisTest"), Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns")); + }), ")\n (methodListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("methodListFour"), view.lookup("platypus"), view.lookup("thisTest"), Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns"), Spacebars.kw({ + a: view.lookup("platypus"), + b: view.lookup("thisTest"), + c: Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), + d: Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns") + })); + }), ")\n (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("helperListFour"), view.lookup("platypus"), view.lookup("thisTest"), Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns")); + }), ")\n (helperListFour platypus thisTest fancyhelper.currentFruit fancyhelper.currentCountry.unicorns a=platypus b=thisTest c=fancyhelper.currentFruit d=fancyhelper.currentCountry.unicorns=", Blaze.View(function() { + return Spacebars.mustache(view.lookup("helperListFour"), view.lookup("platypus"), view.lookup("thisTest"), Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns"), Spacebars.kw({ + a: view.lookup("platypus"), + b: view.lookup("thisTest"), + c: Spacebars.dot(view.lookup("fancyhelper"), "currentFruit"), + d: Spacebars.dot(view.lookup("fancyhelper"), "currentCountry", "unicorns") + })); + }), ")" ]; +})); + +Template.__define__("old_test_render_a", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), HTML.Raw("

") ]; +})); + +Template.__define__("old_test_render_b", (function() { + var view = this; + return Spacebars.With(function() { + return 200; + }, function() { + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), HTML.BR(), HTML.HR() ]; + }); +})); + +Template.__define__("old_test_render_c", (function() { + var view = this; + return HTML.Raw("

"); +})); + +Template.__define__("old_test_template_arg_a", (function() { + var view = this; + return HTML.Raw("Foo Bar Baz"); +})); + +Template.__define__("old_test_template_helpers_a", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("foo")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("bar")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("baz")); + }) ]; +})); + +Template.__define__("old_test_template_helpers_b", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("name")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("arity")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("toString")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("length")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("var")); + }) ]; +})); + +Template.__define__("old_test_template_helpers_c", (function() { + var view = this; + return [ Blaze.View(function() { + return Spacebars.mustache(view.lookup("name")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("arity")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("length")); + }), Blaze.View(function() { + return Spacebars.mustache(view.lookup("var")); + }), "x" ]; +})); + +Template.__define__("old_test_template_events_a", (function() { + var view = this; + return HTML.Raw("foobarbaz"); +})); + +Template.__define__("old_test_template_events_b", (function() { + var view = this; + return HTML.Raw("foobarbaz"); +})); + +Template.__define__("old_test_template_events_c", (function() { + var view = this; + return HTML.Raw("foobarbaz"); +})); + +Template.__define__("old_test_type_casting", (function() { + var view = this; + return Blaze.View(function() { + return Spacebars.mustache(view.lookup("testTypeCasting"), "true", "false", true, false, 0, 1, -1, 10, -10); + }); +})); + +Template.__define__("old_test_template_issue801", (function() { + var view = this; + return Blaze.Each(function() { + return Spacebars.call(view.lookup("values")); + }, function() { + return Blaze.View(function() { + return Spacebars.mustache(view.lookup(".")); + }); + }); +})); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/spacebars-tests/old_templates_tests.js b/packages/spacebars-tests/old_templates_tests.js new file mode 100644 index 0000000000..107e89bc47 --- /dev/null +++ b/packages/spacebars-tests/old_templates_tests.js @@ -0,0 +1,2759 @@ +// +// This file is used to ensure old built templates still work with the +// new Blaze APIs. More in a comment at the top of old_templates.js +// + +var divRendersTo = function (test, div, html) { + Tracker.flush({_throwFirstError: true}); + var actual = canonicalizeHtml(div.innerHTML); + test.equal(actual, html); +}; + +var nodesToArray = function (array) { + // Starting in underscore 1.4, _.toArray does not work right on a node + // list in IE8. This is a workaround to support IE8. + return _.map(array, _.identity); +}; + +var clickIt = function (elem) { + // jQuery's bubbling change event polyfill for IE 8 seems + // to require that the element in question have focus when + // it receives a simulated click. + if (elem.focus) + elem.focus(); + clickElement(elem); +}; + +Tinytest.add("spacebars-tests - old - template_tests - simple helper", function (test) { + var tmpl = Template.old_spacebars_template_test_simple_helper; + var R = ReactiveVar(1); + tmpl.foo = function (x) { + return x + R.get(); + }; + tmpl.bar = function () { + return 123; + }; + var div = renderToDiv(tmpl); + + test.equal(canonicalizeHtml(div.innerHTML), "124"); + R.set(2); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "125"); + + // Test that `{{foo bar}}` throws if `foo` is missing or not a function. + tmpl.foo = 3; + test.throws(function () { + renderToDiv(tmpl); + }, /Can't call non-function/); + + delete tmpl.foo; + test.throws(function () { + renderToDiv(tmpl); + }, /No such function/); + + tmpl.foo = function () {}; + // doesn't throw + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), ''); + + // now "foo" is a function in the data context + delete tmpl.foo; + + R = ReactiveVar(1); + div = renderToDiv(tmpl, { foo: function (x) { + return x + R.get(); + } }); + test.equal(canonicalizeHtml(div.innerHTML), "124"); + R.set(2); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "125"); + + test.throws(function () { + renderToDiv(tmpl, {foo: 3}); + }, /Can't call non-function/); + + test.throws(function () { + renderToDiv(tmpl, {foo: null}); + }, /No such function/); + + test.throws(function () { + renderToDiv(tmpl, {}); + }, /No such function/); +}); + +Tinytest.add("spacebars-tests - old - template_tests - dynamic template", function (test) { + var tmpl = Template.old_spacebars_template_test_dynamic_template; + var aaa = Template.old_spacebars_template_test_aaa; + var bbb = Template.old_spacebars_template_test_bbb; + var R = ReactiveVar("aaa"); + tmpl.foo = function () { + return R.get() === 'aaa' ? aaa : bbb; + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "aaa"); + + R.set('bbb'); + Tracker.flush(); + + test.equal(canonicalizeHtml(div.innerHTML), "bbb"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - interpolate attribute", function (test) { + var tmpl = Template.old_spacebars_template_test_interpolate_attribute; + tmpl.foo = function (x) { + return x+1; + }; + tmpl.bar = function () { + return 123; + }; + var div = renderToDiv(tmpl); + + test.equal($(div).find('div')[0].className, "aaa124zzz"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - dynamic attrs", function (test) { + var tmpl = Template.old_spacebars_template_test_dynamic_attrs; + + var R2 = ReactiveVar({x: "X"}); + var R3 = ReactiveVar('selected'); + tmpl.attrsObj = function () { return R2.get(); }; + tmpl.singleAttr = function () { return R3.get(); }; + + var div = renderToDiv(tmpl); + var span = $(div).find('span')[0]; + test.equal(span.innerHTML, 'hi'); + test.isTrue(span.hasAttribute('selected')); + test.equal(span.getAttribute('x'), 'X'); + + R2.set({y: "Y", z: "Z"}); + R3.set(''); + Tracker.flush(); + test.equal(canonicalizeHtml(span.innerHTML), 'hi'); + test.isFalse(span.hasAttribute('selected')); + test.isFalse(span.hasAttribute('x')); + test.equal(span.getAttribute('y'), 'Y'); + test.equal(span.getAttribute('z'), 'Z'); +}); + +Tinytest.add("spacebars-tests - old - template_tests - triple", function (test) { + var tmpl = Template.old_spacebars_template_test_triple; + + var R = ReactiveVar('blah'); + tmpl.html = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + var elems = $(div).find("> *"); + test.equal(elems.length, 1); + test.equal(elems[0].nodeName, 'SPAN'); + var span = elems[0]; + test.equal(span.className, 'hi'); + test.equal(span.innerHTML, 'blah'); + + R.set('asdf'); + Tracker.flush(); + elems = $(div).find("> *"); + test.equal(elems.length, 0); + test.equal(canonicalizeHtml(div.innerHTML), 'asdf'); + + R.set('blah'); + Tracker.flush(); + elems = $(div).find("> *"); + test.equal(elems.length, 1); + test.equal(elems[0].nodeName, 'SPAN'); + span = elems[0]; + test.equal(span.className, 'hi'); + test.equal(canonicalizeHtml(span.innerHTML), 'blah'); + + var tmpl = Template.old_spacebars_template_test_triple2; + tmpl.html = function () {}; + tmpl.html2 = function () { return null; }; + // no tmpl.html3 + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'xy'); +}); + +Tinytest.add("spacebars-tests - old - template_tests - inclusion args", function (test) { + var tmpl = Template.old_spacebars_template_test_inclusion_args; + + var R = ReactiveVar(Template.old_spacebars_template_test_aaa); + tmpl.foo = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + // `{{> foo bar}}`, with `foo` resolving to Template.aaa, + // which consists of "aaa" + test.equal(canonicalizeHtml(div.innerHTML), 'aaa'); + R.set(Template.old_spacebars_template_test_bbb); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'bbb'); + + ////// Ok, now `foo` *is* Template.aaa + tmpl.foo = Template.old_spacebars_template_test_aaa; + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'aaa'); + + ////// Ok, now `foo` is a template that takes an argument; bar is a string. + tmpl.foo = Template.old_spacebars_template_test_bracketed_this; + tmpl.bar = 'david'; + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), '[david]'); + + ////// Now `foo` is a template that takes an arg; bar is a function. + tmpl.foo = Template.old_spacebars_template_test_span_this; + R = ReactiveVar('david'); + tmpl.bar = function () { return R.get(); }; + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'david'); + var span1 = div.querySelector('span'); + R.set('avi'); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'avi'); + var span2 = div.querySelector('span'); + test.isTrue(span1 === span2); +}); + +Tinytest.add("spacebars-tests - old - template_tests - inclusion args 2", function (test) { + // `{{> foo bar q=baz}}` + var tmpl = Template.old_spacebars_template_test_inclusion_args2; + + tmpl.foo = Template.old_spacebars_template_test_span_this; + tmpl.bar = function (options) { + return options.hash.q; + }; + + var R = ReactiveVar('david!'); + tmpl.baz = function () { return R.get().slice(0,5); }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'david'); + var span1 = div.querySelector('span'); + R.set('brillo'); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'brill'); + var span2 = div.querySelector('span'); + test.isTrue(span1 === span2); +}); + +// maybe use created callback on the template instead of this? +var extendTemplateWithInit = function (template, initFunc) { + var tmpl = new Template(template.viewName+'-extended', template.renderFunction); + tmpl.constructView = function (/*args*/) { + var view = Template.prototype.constructView.apply(this, arguments); + initFunc(view); + return view; + }; + return tmpl; +}; + +Tinytest.add("spacebars-tests - old - template_tests - inclusion dotted args", function (test) { + // `{{> foo bar.baz}}` + var tmpl = Template.old_spacebars_template_test_inclusion_dotted_args; + + var initCount = 0; + tmpl.foo = extendTemplateWithInit( + Template.old_spacebars_template_test_bracketed_this, + function () { initCount++; }); + + var R = ReactiveVar('david'); + tmpl.bar = function () { + // make sure `this` is bound correctly + return { baz: this.symbol + R.get() }; + }; + + var div = renderToDiv(tmpl, {symbol:'%'}); + test.equal(initCount, 1); + test.equal(canonicalizeHtml(div.innerHTML), '[%david]'); + + R.set('avi'); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), '[%avi]'); + // check that invalidating the argument to `foo` doesn't require + // creating a new `foo`. + test.equal(initCount, 1); +}); + +Tinytest.add("spacebars-tests - old - template_tests - inclusion slashed args", function (test) { + // `{{> foo bar/baz}}` + var tmpl = Template.old_spacebars_template_test_inclusion_dotted_args; + + var initCount = 0; + tmpl.foo = extendTemplateWithInit( + Template.old_spacebars_template_test_bracketed_this, + function () { initCount++; }); + var R = ReactiveVar('david'); + tmpl.bar = function () { + // make sure `this` is bound correctly + return { baz: this.symbol + R.get() }; + }; + + var div = renderToDiv(tmpl, {symbol:'%'}); + test.equal(initCount, 1); + test.equal(canonicalizeHtml(div.innerHTML), '[%david]'); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper", function (test) { + // test the case where `foo` is a calculated template that changes + // reactively. + // `{{#foo}}bar{{else}}baz{{/foo}}` + var tmpl = Template.old_spacebars_template_test_block_helper; + var R = ReactiveVar(Template.old_spacebars_template_test_content); + tmpl.foo = function () { + return R.get(); + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "bar"); + + R.set(Template.old_spacebars_template_test_elsecontent); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "baz"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper function with one string arg", function (test) { + // `{{#foo "bar"}}content{{/foo}}` + var tmpl = Template.old_spacebars_template_test_block_helper_function_one_string_arg; + tmpl.foo = function () { + if (String(this) === "bar") + return Template.old_spacebars_template_test_content; + else + return null; + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "content"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper function with one helper arg", function (test) { + var tmpl = Template.old_spacebars_template_test_block_helper_function_one_helper_arg; + var R = ReactiveVar("bar"); + tmpl.bar = function () { return R.get(); }; + tmpl.foo = function () { + if (String(this) === "bar") + return Template.old_spacebars_template_test_content; + else + return null; + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "content"); + + R.set("baz"); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), ""); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper component with one helper arg", function (test) { + var tmpl = Template.old_spacebars_template_test_block_helper_component_one_helper_arg; + var R = ReactiveVar(true); + tmpl.bar = function () { return R.get(); }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "content"); + + R.set(false); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), ""); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper component with three helper args", function (test) { + var tmpl = Template.old_spacebars_template_test_block_helper_component_three_helper_args; + var R = ReactiveVar("bar"); + tmpl.bar_or_baz = function () { + return R.get(); + }; + tmpl.equals = function (x, y) { + return x === y; + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "content"); + + R.set("baz"); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), ""); +}); + +Tinytest.add("spacebars-tests - old - template_tests - block helper with dotted arg", function (test) { + var tmpl = Template.old_spacebars_template_test_block_helper_dotted_arg; + var R1 = ReactiveVar(1); + var R2 = ReactiveVar(10); + var R3 = ReactiveVar(100); + + var initCount = 0; + tmpl.foo = extendTemplateWithInit( + Template.old_spacebars_template_test_bracketed_this, + function () { initCount++; }); + tmpl.bar = function () { + return { + r1: R1.get(), + baz: function (r3) { + return this.r1 + R2.get() + r3; + } + }; + }; + tmpl.qux = function () { return R3.get(); }; + + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "[111]"); + test.equal(initCount, 1); + + R1.set(2); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[112]"); + test.equal(initCount, 1); + + R2.set(20); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[122]"); + test.equal(initCount, 1); + + R3.set(200); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[222]"); + test.equal(initCount, 1); + + R2.set(30); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[232]"); + test.equal(initCount, 1); + + R1.set(3); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[233]"); + test.equal(initCount, 1); + + R3.set(300); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), "[333]"); + test.equal(initCount, 1); +}); + +Tinytest.add("spacebars-tests - old - template_tests - nested content", function (test) { + // Test that `{{> UI.contentBlock}}` in an `{{#if}}` works. + + // ``` + // + // ``` + + // ``` + // {{#spacebars_template_test_iftemplate flag}} + // hello + // {{else}} + // world + // {{/spacebars_template_test_iftemplate}} + // ``` + + var tmpl = Template.old_spacebars_template_test_nested_content; + var R = ReactiveVar(true); + tmpl.flag = function () { + return R.get(); + }; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'hello'); + R.set(false); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'world'); + R.set(true); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'hello'); + + // Also test that `{{> UI.contentBlock}}` in a custom block helper works. + tmpl = Template.old_spacebars_template_test_nested_content2; + R = ReactiveVar(true); + tmpl.x = function () { + return R.get(); + }; + div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'hello'); + R.set(false); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'world'); + R.set(true); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'hello'); +}); + +Tinytest.add("spacebars-tests - old - template_tests - if", function (test) { + var tmpl = Template.old_spacebars_template_test_if; + var R = ReactiveVar(true); + tmpl.foo = function () { + return R.get(); + }; + tmpl.bar = 1; + tmpl.baz = 2; + + var div = renderToDiv(tmpl); + var rendersTo = function (html) { divRendersTo(test, div, html); }; + + rendersTo("1"); + R.set(false); + rendersTo("2"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - if in with", function (test) { + var tmpl = Template.old_spacebars_template_test_if_in_with; + tmpl.foo = {bar: "bar"}; + + var div = renderToDiv(tmpl); + divRendersTo(test, div, "bar bar"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - each on cursor", function (test) { + var tmpl = Template.old_spacebars_template_test_each; + var coll = new Mongo.Collection(null); + tmpl.items = function () { + return coll.find({}, {sort: {pos: 1}}); + }; + + var div = renderToDiv(tmpl); + var rendersTo = function (html) { divRendersTo(test, div, html); }; + + rendersTo("else-clause"); + coll.insert({text: "one", pos: 1}); + rendersTo("one"); + coll.insert({text: "two", pos: 2}); + rendersTo("one two"); + coll.update({text: "two"}, {$set: {text: "three"}}); + rendersTo("one three"); + coll.update({text: "three"}, {$set: {pos: 0}}); + rendersTo("three one"); + coll.remove({}); + rendersTo("else-clause"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - each on array", function (test) { + var tmpl = Template.old_spacebars_template_test_each; + var R = new ReactiveVar([]); + tmpl.items = function () { + return R.get(); + }; + tmpl.text = function () { + return this; + }; + + var div = renderToDiv(tmpl); + var rendersTo = function (html) { divRendersTo(test, div, html); }; + + rendersTo("else-clause"); + R.set([""]); + rendersTo(""); + R.set(["x", "", "toString"]); + rendersTo("x toString"); + R.set(["toString"]); + rendersTo("toString"); + R.set([]); + rendersTo("else-clause"); + R.set([0, 1, 2]); + rendersTo("0 1 2"); + R.set([]); + rendersTo("else-clause"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - ..", function (test) { + var tmpl = Template.old_spacebars_template_test_dots; + Template.old_spacebars_template_test_dots_subtemplate.getTitle = function (from) { + return from.title; + }; + + tmpl.foo = {title: "foo"}; + tmpl.foo.bar = {title: "bar"}; + tmpl.foo.bar.items = [{title: "item"}]; + var div = renderToDiv(tmpl); + + test.equal(canonicalizeHtml(div.innerHTML), [ + "A", "B", "C", "D", + // {{> spacebars_template_test_dots_subtemplate}} + "TITLE", "1item", "2item", "3bar", "4foo", "GETTITLE", "5item", "6bar", "7foo", + // {{> spacebars_template_test_dots_subtemplate ..}} + "TITLE", "1bar", "2bar", "3item", "4bar", "GETTITLE", "5bar", "6item", "7bar"].join(" ")); +}); + +Tinytest.add("spacebars-tests - old - template_tests - select tags", function (test) { + var tmpl = Template.old_spacebars_template_test_select_tag; + + // {label: (string)} + var optgroups = new Mongo.Collection(null); + + // {optgroup: (id), value: (string), selected: (boolean), label: (string)} + var options = new Mongo.Collection(null); + + tmpl.optgroups = function () { return optgroups.find(); }; + tmpl.options = function () { return options.find({optgroup: this._id}); }; + tmpl.selectedAttr = function () { return this.selected ? {selected: true} : {}; }; + + var div = renderToDiv(tmpl); + var selectEl = $(div).find('select')[0]; + + // returns canonicalized contents of `div` in the form eg + // [""]. strip out selected attributes -- we + // verify correctness by observing the `selected` property + var divContent = function () { + return canonicalizeHtml( + div.innerHTML.replace(/selected="[^"]*"/g, '').replace(/selected/g, '')) + .replace(/\>\s*\\n<') + .split('\n'); + }; + + test.equal(divContent(), [""]); + + var optgroup1 = optgroups.insert({label: "one"}); + var optgroup2 = optgroups.insert({label: "two"}); + test.equal(divContent(), [ + '' + ]); + + options.insert({optgroup: optgroup1, value: "value1", selected: false, label: "label1"}); + options.insert({optgroup: optgroup1, value: "value2", selected: true, label: "label2"}); + test.equal(divContent(), [ + '' + ]); + test.equal(selectEl.value, "value2"); + test.equal($(selectEl).find('option')[0].selected, false); + test.equal($(selectEl).find('option')[1].selected, true); + + // swap selection + options.update({value: "value1"}, {$set: {selected: true}}); + options.update({value: "value2"}, {$set: {selected: false}}); + Tracker.flush(); + + test.equal(divContent(), [ + '' + ]); + test.equal(selectEl.value, "value1"); + test.equal($(selectEl).find('option')[0].selected, true); + test.equal($(selectEl).find('option')[1].selected, false); + + // change value and label + options.update({value: "value1"}, {$set: {value: "value1.0"}}); + options.update({value: "value2"}, {$set: {label: "label2.0"}}); + Tracker.flush(); + + test.equal(divContent(), [ + '' + ]); + test.equal(selectEl.value, "value1.0"); + test.equal($(selectEl).find('option')[0].selected, true); + test.equal($(selectEl).find('option')[1].selected, false); + + // unselect and then select both options. normally, the second is + // selected (since it got selected later). then switch to '.slice(0, 30)); + + R.set('bar'); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), + ''); + +}); + +Tinytest.add('spacebars-tests - old - template_tests - no data context', function (test) { + var tmpl = Template.old_spacebars_template_test_no_data; + + // failure is if an exception is thrown here + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'asdf'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - textarea', function (test) { + var tmpl = Template.old_spacebars_template_test_textarea; + + var R = ReactiveVar('hello'); + + tmpl.foo = function () { + return R.get(); + }; + + var div = renderToDiv(tmpl); + var textarea = div.querySelector('textarea'); + test.equal(textarea.value, 'hello'); + + R.set('world'); + Tracker.flush(); + test.equal(textarea.value, 'world'); + +}); + +Tinytest.add('spacebars-tests - old - template_tests - textarea 2', function (test) { + var tmpl = Template.old_spacebars_template_test_textarea2; + + var R = ReactiveVar(true); + + tmpl.foo = function () { + return R.get(); + }; + + var div = renderToDiv(tmpl); + var textarea = div.querySelector('textarea'); + test.equal(textarea.value, '
'); + + R.set(false); + Tracker.flush(); + test.equal(textarea.value, ''); + + R.set(true); + Tracker.flush(); + test.equal(textarea.value, ''); + +}); + +Tinytest.add('spacebars-tests - old - template_tests - textarea 3', function (test) { + var tmpl = Template.old_spacebars_template_test_textarea3; + + var R = ReactiveVar('hello'); + + tmpl.foo = function () { + return R.get(); + }; + + var div = renderToDiv(tmpl); + var textarea = div.querySelector('textarea'); + test.equal(textarea.id, 'myTextarea'); + test.equal(textarea.value, 'hello'); + + R.set('world'); + Tracker.flush(); + test.equal(textarea.value, 'world'); + +}); + +Tinytest.add('spacebars-tests - old - template_tests - textarea each', function (test) { + var tmpl = Template.old_spacebars_template_test_textarea_each; + + var R = ReactiveVar(['APPLE', 'BANANA']); + + tmpl.foo = function () { + return R.get(); + }; + + var div = renderToDiv(tmpl); + var textarea = div.querySelector('textarea'); + test.equal(textarea.value, ''); + + R.set(['CUCUMBER']); + Tracker.flush(); + test.equal(textarea.value, 'Smurf') + result = '
Smurf
'; // e.g. IE 9 and 10 + test.equal(result, '
Smurf
'); + }; + + shouldBe('donut frankfurter noodle'); + coll.remove({name: 'frankfurter'}); // (it was kind of a mouthful) + shouldBe('donut noodle'); + coll.remove({name: 'donut'}); + shouldBe('noodle'); + coll.remove({name: 'noodle'}); + shouldBe(''); // 'David' and 'Steve' appear in the #each but fail the #if + coll.remove({}); + shouldBe('none'); // now the `{{else}}` case kicks in + coll.insert({name: 'bubblegum'}); + shouldBe('bubblegum'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - block helpers in attribute 2', function (test) { + var tmpl = Template.old_spacebars_template_test_block_helpers_in_attribute_2; + + var R = ReactiveVar(true); + + tmpl.foo = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + var input = div.querySelector('input'); + + test.equal(input.value, '"'); + R.set(false); + Tracker.flush(); + test.equal(input.value, '&<>'); +}); + + +// Test that if the argument to #each is a constant, it doesn't establish a +// dependency on the data context, so when the context changes, items of +// the #each are not "changed" and helpers do not rerun. +Tinytest.add('spacebars-tests - old - template_tests - constant #each argument', function (test) { + var tmpl = Template.old_spacebars_template_test_constant_each_argument; + + var justReturnRuns = 0; // how many times `justReturn` is called + var R = ReactiveVar(1); + + tmpl.someData = function () { + return R.get(); + }; + tmpl.anArray = ['foo', 'bar']; + tmpl.justReturn = function (x) { + justReturnRuns++; + return String(x); + }; + + var div = renderToDiv(tmpl); + + test.equal(justReturnRuns, 2); + test.equal(canonicalizeHtml(div.innerHTML).replace(/\s+/g, ' '), + 'foo bar 1'); + + R.set(2); + Tracker.flush(); + + test.equal(justReturnRuns, 2); // still 2, no new runs! + test.equal(canonicalizeHtml(div.innerHTML).replace(/\s+/g, ' '), + 'foo bar 2'); +}); + +Tinytest.addAsync('spacebars-tests - old - template_tests - #markdown - basic', function (test, onComplete) { + var tmpl = Template.old_spacebars_template_test_markdown_basic; + tmpl.obj = {snippet: "hi"}; + tmpl.hi = function () { + return this.snippet; + }; + var div = renderToDiv(tmpl); + + Meteor.call("getAsset", "markdown_basic.html", function (err, html) { + test.isFalse(err); + test.equal(canonicalizeHtml(div.innerHTML), + canonicalizeHtml(html)); + onComplete(); + }); +}); + +testAsyncMulti('spacebars-tests - old - template_tests - #markdown - if', [ + function (test, expect) { + var self = this; + Meteor.call("getAsset", "markdown_if1.html", expect(function (err, html) { + test.isFalse(err); + self.html1 = html; + })); + Meteor.call("getAsset", "markdown_if2.html", expect(function (err, html) { + test.isFalse(err); + self.html2 = html; + })); + }, + + function (test, expect) { + var self = this; + var tmpl = Template.old_spacebars_template_test_markdown_if; + var R = new ReactiveVar(false); + tmpl.cond = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1)); + R.set(true); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2)); + } +]); + +testAsyncMulti('spacebars-tests - old - template_tests - #markdown - each', [ + function (test, expect) { + var self = this; + Meteor.call("getAsset", "markdown_each1.html", expect(function (err, html) { + test.isFalse(err); + self.html1 = html; + })); + Meteor.call("getAsset", "markdown_each2.html", expect(function (err, html) { + test.isFalse(err); + self.html2 = html; + })); + }, + + function (test, expect) { + var self = this; + var tmpl = Template.old_spacebars_template_test_markdown_each; + var R = new ReactiveVar([]); + tmpl.seq = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html1)); + + R.set(["item"]); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), canonicalizeHtml(self.html2)); + } +]); + +Tinytest.add('spacebars-tests - old - template_tests - #markdown - inclusion', function (test) { + var tmpl = Template.old_spacebars_template_test_markdown_inclusion; + var subtmpl = Template.old_spacebars_template_test_markdown_inclusion_subtmpl; + subtmpl.foo = "bar"; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "

Foo is bar.

"); +}); + +Tinytest.add('spacebars-tests - old - template_tests - #markdown - block helpers', function (test) { + var tmpl = Template.old_spacebars_template_test_markdown_block_helpers; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), "

Hi there!

"); +}); + +// Test that when a simple helper re-runs due to a dependency changing +// but the return value is the same, the DOM text node is not +// re-rendered. +Tinytest.add('spacebars-tests - old - template_tests - simple helpers are isolated', function (test) { + var runs = [{ + helper: function () { return "foo"; }, + nodeValue: "foo" + }, { + helper: function () { return new Spacebars.SafeString("bar"); }, + nodeValue: "bar" + }]; + + _.each(runs, function (run) { + var tmpl = Template.old_spacebars_template_test_simple_helpers_are_isolated; + var dep = new Tracker.Dependency; + tmpl.foo = function () { + dep.depend(); + return run.helper(); + }; + var div = renderToDiv(tmpl); + var fooTextNode = _.find(div.childNodes, function (node) { + return node.nodeValue === run.nodeValue; + }); + + test.isTrue(fooTextNode); + + dep.changed(); + Tracker.flush(); + var newFooTextNode = _.find(div.childNodes, function (node) { + return node.nodeValue === run.nodeValue; + }); + + test.equal(fooTextNode, newFooTextNode); + }); +}); + +// Test that when a helper in an element attribute re-runs due to a +// dependency changing but the return value is the same, the attribute +// value is not set. +Tinytest.add('spacebars-tests - old - template_tests - attribute helpers are isolated', function (test) { + var tmpl = Template.old_spacebars_template_test_attr_helpers_are_isolated; + var dep = new Tracker.Dependency; + tmpl.foo = function () { + dep.depend(); + return "foo"; + }; + var div = renderToDiv(tmpl); + var pElement = div.querySelector('p'); + + test.equal(pElement.getAttribute('attr'), 'foo'); + + // set the attribute to something else, afterwards check that it + // hasn't been updated back to the correct value. + pElement.setAttribute('attr', 'not-foo'); + dep.changed(); + Tracker.flush(); + test.equal(pElement.getAttribute('attr'), 'not-foo'); +}); + +// A helper can return an object with a set of element attributes via +// `

`. When it re-runs due to a dependency changing the +// value for a given attribute might stay the same. Test that the +// attribute is not set on the DOM element. +Tinytest.add('spacebars-tests - old - template_tests - attribute object helpers are isolated', function (test) { + var tmpl = Template.old_spacebars_template_test_attr_object_helpers_are_isolated; + var dep = new Tracker.Dependency; + tmpl.attrs = function () { + dep.depend(); + return {foo: "bar"}; + }; + var div = renderToDiv(tmpl); + var pElement = div.querySelector('p'); + + test.equal(pElement.getAttribute('foo'), 'bar'); + + // set the attribute to something else, afterwards check that it + // hasn't been updated back to the correct value. + pElement.setAttribute('foo', 'not-bar'); + dep.changed(); + Tracker.flush(); + test.equal(pElement.getAttribute('foo'), 'not-bar'); +}); + +// Test that when a helper in an inclusion directive (`{{> foo }}`) +// re-runs due to a dependency changing but the return value is the +// same, the template is not re-rendered. +// +// Also, verify that an error is thrown if the return value from such +// a helper is not a component. +Tinytest.add('spacebars-tests - old - template_tests - inclusion helpers are isolated', function (test) { + var tmpl = Template.old_spacebars_template_test_inclusion_helpers_are_isolated; + var dep = new Tracker.Dependency; + var subtmpl = Template.old_spacebars_template_test_inclusion_helpers_are_isolated_subtemplate; + // make a copy so we can set "rendered" without mutating the original + var subtmplCopy = new Template(subtmpl.viewName, subtmpl.renderFunction); + + var R = new ReactiveVar(subtmplCopy); + tmpl.foo = function () { + dep.depend(); + return R.get(); + }; + + var div = renderToDiv(tmpl); + subtmplCopy.rendered = function () { + test.fail("shouldn't re-render when same value returned from helper"); + }; + + dep.changed(); + Tracker.flush({_throwFirstError: true}); // `subtmplCopy.rendered` not called + + R.set(null); + Tracker.flush({_throwFirstError: true}); // no error thrown + + R.set("neither a component nor null"); + + test.throws(function () { + Tracker.flush({_throwFirstError: true}); + }, /Expected template or null/); +}); + +Tinytest.add('spacebars-tests - old - template_tests - nully attributes', function (test) { + var tmpls = { + 0: Template.old_spacebars_template_test_nully_attributes0, + 1: Template.old_spacebars_template_test_nully_attributes1, + 2: Template.old_spacebars_template_test_nully_attributes2, + 3: Template.old_spacebars_template_test_nully_attributes3, + 4: Template.old_spacebars_template_test_nully_attributes4, + 5: Template.old_spacebars_template_test_nully_attributes5, + 6: Template.old_spacebars_template_test_nully_attributes6 + }; + + var run = function (whichTemplate, data, expectTrue) { + var div = renderToDiv(tmpls[whichTemplate], data); + var input = div.querySelector('input'); + var descr = JSON.stringify([whichTemplate, data, expectTrue]); + if (expectTrue) { + test.isTrue(input.checked, descr); + test.equal(typeof input.getAttribute('stuff'), 'string', descr); + } else { + test.isFalse(input.checked); + test.equal(JSON.stringify(input.getAttribute('stuff')), 'null', descr); + } + + var html = Blaze.toHTML(Blaze.With(data, function () { + return tmpls[whichTemplate]; + })); + + test.equal(/ checked="[^"]*"/.test(html), !! expectTrue); + test.equal(/ stuff="[^"]*"/.test(html), !! expectTrue); + }; + + run(0, {}, true); + + var truthies = [true, '']; + var falsies = [false, null, undefined]; + + _.each(truthies, function (x) { + run(1, {foo: x}, true); + }); + _.each(falsies, function (x) { + run(1, {foo: x}, false); + }); + + _.each(truthies, function (x) { + _.each(truthies, function (y) { + run(2, {foo: x, bar: y}, true); + }); + _.each(falsies, function (y) { + run(2, {foo: x, bar: y}, true); + }); + }); + _.each(falsies, function (x) { + _.each(truthies, function (y) { + run(2, {foo: x, bar: y}, true); + }); + _.each(falsies, function (y) { + run(2, {foo: x, bar: y}, false); + }); + }); + + run(3, {foo: true}, false); + run(3, {foo: false}, false); +}); + +Tinytest.add("spacebars-tests - old - template_tests - double", function (test) { + var tmpl = Template.old_spacebars_template_test_double; + + var run = function (foo, expectedResult) { + tmpl.foo = foo; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), expectedResult); + }; + + run('asdf', 'asdf'); + run(1.23, '1.23'); + run(0, '0'); + run(true, 'true'); + run(false, ''); + run(null, ''); + run(undefined, ''); +}); + +Tinytest.add("spacebars-tests - old - template_tests - inclusion lookup order", function (test) { + // test that {{> foo}} looks for a helper named 'foo', then a + // template named 'foo', then a 'foo' field in the data context. + var tmpl = Template.old_spacebars_template_test_inclusion_lookup; + var tmplData = function () { + return { + // shouldn't have an effect since we define a helper with the + // same name. + old_spacebars_template_test_inclusion_lookup_subtmpl: Template. + old_spacebars_template_test_inclusion_lookup_subtmpl3, + dataContextSubtmpl: Template. + old_spacebars_template_test_inclusion_lookup_subtmpl3}; + }; + + tmpl.old_spacebars_template_test_inclusion_lookup_subtmpl = + Template.old_spacebars_template_test_inclusion_lookup_subtmpl2; + + test.equal(canonicalizeHtml(renderToDiv(tmpl, tmplData).innerHTML), + ["This is generated by a helper with the same name.", + "This is a template passed in the data context."].join(' ')); +}); + +Tinytest.add("spacebars-tests - old - template_tests - content context", function (test) { + var tmpl = Template.old_spacebars_template_test_content_context; + var R = ReactiveVar(true); + tmpl.foo = { + firstLetter: 'F', + secondLetter: 'O', + bar: { + cond: function () { return R.get(); }, + firstLetter: 'B', + secondLetter: 'A' + } + }; + + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'BO'); + R.set(false); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'FA'); +}); + +_.each(['textarea', 'text', 'password', 'submit', 'button', + 'reset', 'select', 'hidden'], function (type) { + Tinytest.add("spacebars-tests - old - template_tests - controls - " + type, function(test) { + var R = ReactiveVar({x:"test"}); + var R2 = ReactiveVar(""); + var tmpl; + + if (type === 'select') { + tmpl = Template.old_spacebars_test_control_select; + tmpl.options = ['This is a test', 'This is a fridge', + 'This is a frog', 'This is a new frog', 'foobar', + 'This is a photograph', 'This is a monkey', + 'This is a donkey']; + tmpl.selected = function () { + R2.get(); // Re-render when R2 is changed, even though it + // doesn't affect HTML. + return ('This is a ' + R.get().x) === this.toString(); + }; + } else if (type === 'textarea') { + tmpl = Template.old_spacebars_test_control_textarea; + tmpl.value = function () { + R2.get(); // Re-render when R2 is changed, even though it + // doesn't affect HTML. + return 'This is a ' + R.get().x; + }; + } else { + tmpl = Template.old_spacebars_test_control_input; + tmpl.value = function () { + R2.get(); // Re-render when R2 is changed, even though it + // doesn't affect HTML. + return 'This is a ' + R.get().x; + }; + tmpl.type = type; + }; + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + var canFocus = (type !== 'hidden'); + + // find first element child, ignoring any marker nodes + var input = div.firstChild; + while (input.nodeType !== 1) + input = input.nextSibling; + + if (type === 'textarea' || type === 'select') { + test.equal(input.nodeName, type.toUpperCase()); + } else { + test.equal(input.nodeName, 'INPUT'); + test.equal(input.type, type); + } + test.equal(DomUtils.getElementValue(input), "This is a test"); + + // value updates reactively + R.set({x:"fridge"}); + Tracker.flush(); + test.equal(DomUtils.getElementValue(input), "This is a fridge"); + + if (canFocus) { + // ...if focused, it still updates but focus isn't lost. + focusElement(input); + DomUtils.setElementValue(input, "something else"); + R.set({x:"frog"}); + + Tracker.flush(); + test.equal(DomUtils.getElementValue(input), "This is a frog"); + test.equal(document.activeElement, input); + } + + // Setting a value (similar to user typing) should prevent value from being + // reverted if the div is re-rendered but the rendered value (ie, R) does + // not change. + DomUtils.setElementValue(input, "foobar"); + R2.set("change"); + Tracker.flush(); + test.equal(DomUtils.getElementValue(input), "foobar"); + + // ... but if the actual rendered value changes, that should take effect. + R.set({x:"photograph"}); + Tracker.flush(); + test.equal(DomUtils.getElementValue(input), "This is a photograph"); + + document.body.removeChild(div); + }); +}); + +Tinytest.add("spacebars-tests - old - template_tests - radio", function(test) { + var R = ReactiveVar(""); + var R2 = ReactiveVar(""); + var change_buf = []; + var tmpl = Template.old_spacebars_test_control_radio; + tmpl.bands = ["AM", "FM", "XM"]; + tmpl.isChecked = function () { + return R.get() === this.toString(); + }; + tmpl.band = function () { + return R.get(); + }; + tmpl.events({ + 'change input': function (event) { + var btn = event.target; + var band = btn.value; + change_buf.push(band); + R.set(band); + } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + + // get the three buttons; they should not change identities! + var btns = nodesToArray(div.getElementsByTagName("INPUT")); + var text = function () { + var text = div.innerText || div.textContent; + return text.replace(/[ \n\r]+/g, " "); + }; + + test.equal(_.pluck(btns, 'checked'), [false, false, false]); + test.equal(text(), "Band: "); + + clickIt(btns[0]); + test.equal(change_buf, ['AM']); + change_buf.length = 0; + Tracker.flush(); + test.equal(_.pluck(btns, 'checked'), [true, false, false]); + test.equal(text(), "Band: AM"); + + R2.set("change"); + Tracker.flush(); + test.length(change_buf, 0); + test.equal(_.pluck(btns, 'checked'), [true, false, false]); + test.equal(text(), "Band: AM"); + + clickIt(btns[1]); + test.equal(change_buf, ['FM']); + change_buf.length = 0; + Tracker.flush(); + test.equal(_.pluck(btns, 'checked'), [false, true, false]); + test.equal(text(), "Band: FM"); + + clickIt(btns[2]); + test.equal(change_buf, ['XM']); + change_buf.length = 0; + Tracker.flush(); + test.equal(_.pluck(btns, 'checked'), [false, false, true]); + test.equal(text(), "Band: XM"); + + clickIt(btns[1]); + test.equal(change_buf, ['FM']); + change_buf.length = 0; + Tracker.flush(); + test.equal(_.pluck(btns, 'checked'), [false, true, false]); + test.equal(text(), "Band: FM"); + + document.body.removeChild(div); +}); + +Tinytest.add("spacebars-tests - old - template_tests - checkbox", function(test) { + var tmpl = Template.old_spacebars_test_control_checkbox; + tmpl.labels = ["Foo", "Bar", "Baz"]; + var Rs = {}; + _.each(tmpl.labels, function (label) { + Rs[label] = ReactiveVar(false); + }); + tmpl.isChecked = function () { + return Rs[this.toString()].get(); + }; + var changeBuf = []; + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + + var boxes = nodesToArray(div.getElementsByTagName("INPUT")); + + test.equal(_.pluck(boxes, 'checked'), [false, false, false]); + + // Re-render with first one checked. + Rs.Foo.set(true); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [true, false, false]); + + // Re-render with first one unchecked again. + Rs.Foo.set(false); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [false, false, false]); + + // User clicks the second one. + clickElement(boxes[1]); + test.equal(_.pluck(boxes, 'checked'), [false, true, false]); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [false, true, false]); + + // Re-render with third one checked. Second one should stay checked because + // it's a user update! + Rs.Baz.set(true); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [false, true, true]); + + // User turns second and third off. + clickElement(boxes[1]); + clickElement(boxes[2]); + test.equal(_.pluck(boxes, 'checked'), [false, false, false]); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [false, false, false]); + + // Re-render with first one checked. Third should stay off because it's a user + // update! + Rs.Foo.set(true); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [true, false, false]); + + // Re-render with first one unchecked. Third should still stay off. + Rs.Foo.set(false); + Tracker.flush(); + test.equal(_.pluck(boxes, 'checked'), [false, false, false]); + + document.body.removeChild(div); +}); + +Tinytest.add('spacebars-tests - old - template_tests - unfound template', function (test) { + test.throws(function () { + renderToDiv(Template.old_spacebars_test_nonexistent_template); + }, /No such template/); +}); + +Tinytest.add('spacebars-tests - old - template_tests - helper passed to #if called exactly once when invalidated', function (test) { + var tmpl = Template.old_spacebars_test_if_helper; + + var count = 0; + var d = new Tracker.Dependency; + tmpl.foo = function () { + d.depend(); + count++; + return foo; + }; + + foo = false; + var div = renderToDiv(tmpl); + divRendersTo(test, div, "false"); + test.equal(count, 1); + + foo = true; + d.changed(); + divRendersTo(test, div, "true"); + test.equal(count, 2); +}); + +Tinytest.add('spacebars-tests - old - template_tests - custom block helper functions called exactly once when invalidated', function (test) { + var tmpl = Template.old_spacebars_test_block_helper_function; + + var count = 0; + var d = new Tracker.Dependency; + tmpl.foo = function () { + d.depend(); + count++; + return Template.old_spacebars_template_test_aaa; + }; + + foo = false; + renderToDiv(tmpl); + Tracker.flush(); + test.equal(count, 1); + + foo = true; + d.changed(); + Tracker.flush(); + test.equal(count, 2); +}); + +var runOneTwoTest = function (test, subTemplateName, optionsData) { + _.each([Template.old_spacebars_test_helpers_stop_onetwo, + Template.old_spacebars_test_helpers_stop_onetwo_attribute], + function (tmpl) { + + tmpl.one = Template[subTemplateName + '1']; + tmpl.two = Template[subTemplateName + '2']; + + var buf = ''; + + var showOne = ReactiveVar(true); + var dummy = ReactiveVar(0); + + tmpl.showOne = function () { return showOne.get(); }; + tmpl.one.options = function () { + var x = dummy.get(); + buf += '1'; + if (optionsData) + return optionsData[x]; + else + return ['something']; + }; + tmpl.two.options = function () { + var x = dummy.get(); + buf += '2'; + if (optionsData) + return optionsData[x]; + else + return ['something']; + }; + + var div = renderToDiv(tmpl); + Tracker.flush(); + test.equal(buf, '1'); + + showOne.set(false); + dummy.set(1); + Tracker.flush(); + test.equal(buf, '12'); + + showOne.set(true); + dummy.set(2); + Tracker.flush(); + test.equal(buf, '121'); + + // clean up the div + $(div).remove(); + test.equal(showOne._numListeners(), 0); + test.equal(dummy._numListeners(), 0); + }); +}; + +Tinytest.add('spacebars-tests - old - template_tests - with stops without re-running helper', function (test) { + runOneTwoTest(test, 'spacebars_test_helpers_stop_with'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - each stops without re-running helper', function (test) { + runOneTwoTest(test, 'spacebars_test_helpers_stop_each'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - each inside with stops without re-running helper', function (test) { + runOneTwoTest(test, 'spacebars_test_helpers_stop_with_each'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - if stops without re-running helper', function (test) { + runOneTwoTest(test, 'spacebars_test_helpers_stop_if', ['a', 'b', 'a']); +}); + +Tinytest.add('spacebars-tests - old - template_tests - unless stops without re-running helper', function (test) { + runOneTwoTest(test, 'spacebars_test_helpers_stop_unless', ['a', 'b', 'a']); +}); + +Tinytest.add('spacebars-tests - old - template_tests - inclusion stops without re-running function', function (test) { + var t = Template.old_spacebars_test_helpers_stop_inclusion3; + runOneTwoTest(test, 'spacebars_test_helpers_stop_inclusion', [t, t, t]); +}); + +Tinytest.add('spacebars-tests - old - template_tests - template with callbacks inside with stops without recalculating data', function (test) { + var tmpl = Template.old_spacebars_test_helpers_stop_with_callbacks3; + tmpl.created = function () {}; + tmpl.rendered = function () {}; + tmpl.destroyed = function () {}; + runOneTwoTest(test, 'spacebars_test_helpers_stop_with_callbacks'); +}); + +Tinytest.add('spacebars-tests - old - template_tests - no data context is seen as an empty object', function (test) { + var tmpl = Template.old_spacebars_test_no_data_context; + + var dataInHelper = 'UNSET'; + var dataInRendered = 'UNSET'; + var dataInCreated = 'UNSET'; + var dataInDestroyed = 'UNSET'; + var dataInEvent = 'UNSET'; + + tmpl.foo = function () { + dataInHelper = this; + }; + tmpl.created = function () { + dataInCreated = this.data; + }; + tmpl.rendered = function () { + dataInRendered = this.data; + }; + tmpl.destroyed = function () { + dataInDestroyed = this.data; + }; + tmpl.events({ + 'click': function () { + dataInEvent = this; + } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + clickElement(div.querySelector('button')); + Tracker.flush(); // rendered gets called afterFlush + $(div).remove(); + + test.isFalse(dataInHelper === window); + test.equal(dataInHelper, {}); + test.equal(dataInCreated, null); + test.equal(dataInRendered, null); + test.equal(dataInDestroyed, null); + test.isFalse(dataInEvent === window); + test.equal(dataInEvent, {}); +}); + +Tinytest.add('spacebars-tests - old - template_tests - falsy with', function (test) { + var tmpl = Template.old_spacebars_test_falsy_with; + var R = ReactiveVar(null); + tmpl.obj = function () { return R.get(); }; + + var div = renderToDiv(tmpl); + divRendersTo(test, div, ""); + + R.set({greekLetter: 'alpha'}); + divRendersTo(test, div, "alpha"); + + R.set(null); + divRendersTo(test, div, ""); + + R.set({greekLetter: 'alpha'}); + divRendersTo(test, div, "alpha"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - helpers don't leak", function (test) { + var tmpl = Template.old_spacebars_test_helpers_dont_leak; + tmpl.foo = "wrong"; + tmpl.bar = function () { return "WRONG"; }; + + // Also test that custom block helpers (implemented as templates) do NOT + // interfere with helper lookup in the current template + Template.old_spacebars_test_helpers_dont_leak2.bonus = + function () { return 'BONUS'; }; + + var div = renderToDiv(tmpl); + divRendersTo(test, div, "correct BONUS"); +}); + +Tinytest.add("spacebars-tests - old - template_tests - event handler returns false", + function (test) { + var tmpl = Template.old_spacebars_test_event_returns_false; + var elemId = "spacebars_test_event_returns_false_link"; + tmpl.events({ + 'click a': function (evt) { return false; } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + clickIt(document.getElementById(elemId)); + // NOTE: This failure can stick across test runs! Try + // removing '#bad-url' from the location bar and run + // the tests again. :) + test.isFalse(/#bad-url/.test(window.location.hash)); + document.body.removeChild(div); + } +); + +// Make sure that if you bind an event on "div p", for example, +// both the div and the p need to be in the template. jQuery's +// `$(elem).find(...)` works this way, but the browser's +// querySelector doesn't. +Tinytest.add( + "spacebars-tests - old - template_tests - event map selector scope", + function (test) { + var tmpl = Template.old_spacebars_test_event_selectors1; + var tmpl2 = Template.old_spacebars_test_event_selectors2; + var buf = []; + tmpl2.events({ + 'click div p': function (evt) { buf.push(evt.currentTarget.className); } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + test.equal(buf.join(), ''); + clickIt(div.querySelector('.p1')); + test.equal(buf.join(), ''); + clickIt(div.querySelector('.p2')); + test.equal(buf.join(), 'p2'); + document.body.removeChild(div); + } +); + +if (document.addEventListener) { + // see note about non-bubbling events in the "capuring events" + // templating test for why we use the VIDEO tag. (It would be + // nice to get rid of the network dependency, though.) + // We skip this test in IE 8. + Tinytest.add( + "spacebars-tests - old - template_tests - event map selector scope (capturing)", + function (test) { + var tmpl = Template.old_spacebars_test_event_selectors_capturing1; + var tmpl2 = Template.old_spacebars_test_event_selectors_capturing2; + var buf = []; + tmpl2.events({ + 'play div video': function (evt) { buf.push(evt.currentTarget.className); } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + test.equal(buf.join(), ''); + simulateEvent(div.querySelector(".video1"), + "play", {}, {bubbles: false}); + test.equal(buf.join(), ''); + simulateEvent(div.querySelector(".video2"), + "play", {}, {bubbles: false}); + test.equal(buf.join(), 'video2'); + document.body.removeChild(div); + } + ); +} + +Tinytest.add("spacebars-tests - old - template_tests - tables", function (test) { + var tmpl1 = Template.old_spacebars_test_tables1; + + var div = renderToDiv(tmpl1); + test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'), + ['TABLE', 'TR', 'TD']); + divRendersTo(test, div, '
Foo
'); + + var tmpl2 = Template.old_spacebars_test_tables2; + tmpl2.foo = 'Foo'; + div = renderToDiv(tmpl2); + test.equal(_.pluck(div.querySelectorAll('*'), 'tagName'), + ['TABLE', 'TR', 'TD']); + divRendersTo(test, div, '
Foo
'); +}); + +Tinytest.add("spacebars-tests - old - template_tests - jQuery.trigger extraParameters are passed to the event callback", + function (test) { + var tmpl = Template.old_spacebars_test_jquery_events; + var captured = false; + var args = ["param1", "param2", {option: 1}, 1, 2, 3]; + + tmpl.events({ + 'someCustomEvent': function (event, template) { + var i; + for (i=0; i elements", + function (test) { + if (! document.createElementNS) { + // IE 8 + return; + } + + var tmpl = Template.old_spacebars_test_svg_anchor; + var div = renderToDiv(tmpl); + + var anchNamespace = $(div).find("a").get(0).namespaceURI; + test.equal(anchNamespace, "http://www.w3.org/2000/svg"); + } +); + +Tinytest.add( + "spacebars-tests - old - template_tests - created/rendered/destroyed by each", + function (test) { + var outerTmpl = + Template.old_spacebars_test_template_created_rendered_destroyed_each; + var innerTmpl = + Template.old_spacebars_test_template_created_rendered_destroyed_each_sub; + + var buf = ''; + + innerTmpl.created = function () { buf += 'C' + String(this.data).toLowerCase(); }; + innerTmpl.rendered = function () { buf += 'R' + String(this.data).toLowerCase(); }; + innerTmpl.destroyed = function () { buf += 'D' + String(this.data).toLowerCase(); }; + + var R = ReactiveVar([{_id: 'A'}]); + + outerTmpl.items = function () { + return R.get(); + }; + + var div = renderToDiv(outerTmpl); + divRendersTo(test, div, '

A
'); + test.equal(buf, 'CaRa'); + + R.set([{_id: 'B'}]); + divRendersTo(test, div, '
B
'); + test.equal(buf, 'CaRaDaCbRb'); + + R.set([{_id: 'C'}]); + divRendersTo(test, div, '
C
'); + test.equal(buf, 'CaRaDaCbRbDbCcRc'); + + $(div).remove(); + test.equal(buf, 'CaRaDaCbRbDbCcRcDc'); + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - UI.render/UI.remove", + function (test) { + var div = document.createElement("DIV"); + document.body.appendChild(div); + + var created = false, rendered = false, destroyed = false; + var R = ReactiveVar('aaa'); + + var tmpl = Template.old_spacebars_test_ui_render; + tmpl.greeting = function () { return this.greeting || 'Hello'; }; + tmpl.r = function () { return R.get(); }; + tmpl.created = function () { created = true; }; + tmpl.rendered = function () { rendered = true; }; + tmpl.destroyed = function () { destroyed = true; }; + + test.equal([created, rendered, destroyed], [false, false, false]); + + var renderedTmpl = UI.render(tmpl, div); + test.equal([created, rendered, destroyed], [true, false, false]); + + // Flush now. We fire the rendered callback in an afterFlush block, + // to ensure that the DOM is completely updated. + Tracker.flush(); + test.equal([created, rendered, destroyed], [true, true, false]); + + var otherDiv = document.createElement("DIV"); + // can run a second time without throwing + var x = UI.render(tmpl, otherDiv); + // note: we'll have clean up `x` below + + var renderedTmpl2 = UI.renderWithData( + tmpl, {greeting: 'Bye'}, div); + test.equal(canonicalizeHtml(div.innerHTML), + "Hello aaaBye aaa"); + R.set('bbb'); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), + "Hello bbbBye bbb"); + test.equal([created, rendered, destroyed], [true, true, false]); + test.equal(R._numListeners(), 3); + UI.remove(renderedTmpl); + UI.remove(renderedTmpl); // test that double-remove doesn't throw + UI.remove(renderedTmpl2); + UI.remove(x); + test.equal([created, rendered, destroyed], [true, true, true]); + test.equal(R._numListeners(), 0); + test.equal(canonicalizeHtml(div.innerHTML), ""); + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - UI.render fails on jQuery objects", + function (test) { + var tmpl = Template.old_spacebars_test_ui_render; + test.throws(function () { + UI.render(tmpl, $('body')); + }, /'parentElement' must be a DOM node/); + test.throws(function () { + UI.render(tmpl, document.body, $('body')); + }, /'nextNode' must be a DOM node/); + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - UI.getElementData", + function (test) { + var div = document.createElement("DIV"); + var tmpl = Template.old_spacebars_test_ui_getElementData; + UI.renderWithData(tmpl, {foo: "bar"}, div); + + var span = div.querySelector('SPAN'); + test.isTrue(span); + test.equal(UI.getElementData(span), {foo: "bar"}); + test.equal(Blaze.getData(span), {foo: "bar"}); + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - autorun cleanup", + function (test) { + var tmpl = Template.old_spacebars_test_parent_removal; + + var Acalls = ''; + var A = ReactiveVar('hi'); + tmpl.A = function (chr) { + Acalls += chr; + return A.get(); + }; + var Bcalls = 0; + var B = ReactiveVar(['one', 'two']); + tmpl.B = function () { + Bcalls++; + return B.get(); + }; + + // Assert how many times A and B were accessed (since last time) + // and how many autoruns are listening to them. + var assertCallsAndListeners = + function (a_calls, b_calls, a_listeners, b_listeners) { + test.equal('A calls: ' + Acalls.length, + 'A calls: ' + a_calls, + Acalls); + test.equal('B calls: ' + Bcalls, + 'B calls: ' + b_calls); + test.equal('A listeners: ' + A._numListeners(), + 'A listeners: ' + a_listeners); + test.equal('B listeners: ' + B._numListeners(), + 'B listeners: ' + b_listeners); + Acalls = ''; + Bcalls = 0; + }; + + var div = renderToDiv(tmpl); + assertCallsAndListeners(10, 1, 10, 1); + A.set(''); + Tracker.flush(); + // Confirm that #4, #5, #6, and #9 are not re-run. + // #a is newly run, for a total of 10 - 4 + 1 = 7, + assertCallsAndListeners(7, 0, 7, 1); + A.set('hi'); + Tracker.flush(); + assertCallsAndListeners(10, 0, 10, 1); + + // Now see that removing the DOM with jQuery, below + // the level of the entire template, stops everything. + $(div.querySelector('.toremove')).remove(); + assertCallsAndListeners(0, 0, 0, 0); + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - focus/blur with clean-up", + function (test) { + var tmpl = Template.old_spacebars_test_focus_blur_outer; + var cond = ReactiveVar(true); + tmpl.cond = function () { + return cond.get(); + }; + var buf = []; + Template.old_spacebars_test_focus_blur_inner.events({ + 'focus input': function () { + buf.push('FOCUS'); + }, + 'blur input': function () { + buf.push('BLUR'); + } + }); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + + // check basic focus and blur to make sure + // everything is sane + test.equal(div.querySelectorAll('input').length, 1); + var input; + focusElement(input = div.querySelector('input')); + // We don't get focus events when the Chrome Dev Tools are focused, + // unfortunately, as of Chrome 35. I think this is a regression in + // Chrome 34. So, the goal is to work whether or not focus is + // "borken," where "working" means always failing if DOMBackend isn't + // correctly unbinding the old event handlers when we switch the IF, + // and always passing if it is. To cause the problem in DOMBackend, + // delete the '**' argument to jQuery#off in + // DOMBackend.Events.undelegateEvents. The only compromise we are + // making here is that if some unrelated bug in Blaze makes + // focus/blur not work, the failure might be masked while the Dev + // Tools are open. + var borken = false; + if (buf.length === 0 && document.activeElement === input) { + test.ok({note:"You might need to defocus the Chrome Dev Tools to get a more accurate run of this test!"}); + borken = true; + $(input).trigger('focus'); + } + test.equal(buf.join(), 'FOCUS'); + blurElement(div.querySelector('input')); + if (buf.length === 1) + $(input).trigger('blur'); + test.equal(buf.join(), 'FOCUS,BLUR'); + + // now switch the IF and check again. The failure mode + // we observed was that DOMBackend would not correctly + // unbind the old event listener at the jQuery level, + // so the old event listener would fire and cause an + // exception inside Blaze ("Must be attached" in + // DOMRange#containsElement), which would show up in + // the console and cause our handler not to fire. + cond.set(false); + buf.length = 0; + Tracker.flush(); + test.equal(div.querySelectorAll('input').length, 1); + focusElement(input = div.querySelector('input')); + if (borken) + $(input).trigger('focus'); + test.equal(buf.join(), 'FOCUS'); + blurElement(div.querySelector('input')); + if (! borken) + test.equal(buf.join(), 'FOCUS,BLUR'); + + document.body.removeChild(div); + }); + +// We used to remove event handlers on DOMRange detached, but when +// tearing down a view, we don't "detach" all the DOMRanges recursively. +// Mainly, we destroy the View. Destroying a View should remove its +// event listeners. (In practice, however, it's hard to think of +// consequences to not removing event handlers on removed DOM nodes, +// which will probably be GCed anyway.) +Tinytest.add( + "spacebars-tests - old - template_tests - event cleanup on destroyed", + function (test) { + var tmpl = Template.old_spacebars_test_event_cleanup_on_destroyed_outer; + var cond = ReactiveVar(true); + tmpl.cond = function () { + return cond.get(); + }; + + Template.old_spacebars_test_event_cleanup_on_destroyed_inner.events({ + 'click span': function () {}}); + + var div = renderToDiv(tmpl); + document.body.appendChild(div); + + var eventDiv = div.querySelector('div'); + test.equal(eventDiv.$blaze_events.click.handlers.length, 1); + + cond.set(false); + Tracker.flush(); + test.equal(eventDiv.$blaze_events.click.handlers.length, 0); + + document.body.removeChild(div); + }); + +_.each([1, 2, 3], function (n) { + Tinytest.add( + "spacebars-tests - old - template_tests - lookup is isolated " + n, + function (test) { + var buf = ""; + var inclusion = Template.old_spacebars_test_isolated_lookup_inclusion; + inclusion.created = function () { buf += 'C'; }; + inclusion.destroyed = function () { buf += 'D'; }; + + var tmpl = Template['old_spacebars_test_isolated_lookup' + n]; + var R = ReactiveVar(Template.old_spacebars_template_test_aaa); + + tmpl.bar = function () { + return R.get(); + }; + + var div = renderToDiv( + tmpl, + function () { + return { foo: R.get() }; + }); + + test.equal(canonicalizeHtml(div.innerHTML), 'aaa--x'); + test.equal(buf, 'C'); + R.set(Template.old_spacebars_template_test_bbb); + Tracker.flush(); + test.equal(canonicalizeHtml(div.innerHTML), 'bbb--x'); + test.equal(buf, 'C'); + } + ); +}); + +Tinytest.add('spacebars-tests - old - template_tests - current view in event handler', function (test) { + var tmpl = Template.old_spacebars_test_current_view_in_event; + + var currentView; + var currentData; + + tmpl.events({ + 'click span': function () { + currentView = Blaze.getView(); + currentData = Blaze.getData(); + } + }); + + var div = renderToDiv(tmpl, 'blah'); + test.equal(canonicalizeHtml(div.innerHTML), 'blah'); + document.body.appendChild(div); + clickElement(div.querySelector('span')); + $(div).remove(); + + test.isTrue(currentView); + test.equal(currentData, 'blah'); +}); + + +Tinytest.add( + "spacebars-tests - old - template_tests - textarea attrs", function (test) { + var tmplNoContents = { + tmpl: Template.old_spacebars_test_textarea_attrs, + hasTextAreaContents: false + }; + var tmplWithContents = { + tmpl: Template.old_spacebars_test_textarea_attrs_contents, + hasTextAreaContents: true + }; + var tmplWithContentsAndMoreAttrs = { + tmpl: Template.old_spacebars_test_textarea_attrs_array_contents, + hasTextAreaContents: true + }; + + _.each( + [tmplNoContents, tmplWithContents, + tmplWithContentsAndMoreAttrs], + function (tmplInfo) { + + var id = new ReactiveVar("textarea-" + Random.id()); + var name = new ReactiveVar("one"); + var attrs = new ReactiveVar({ + id: "textarea-" + Random.id() + }); + + var div = renderToDiv(tmplInfo.tmpl, { + attrs: function () { + return attrs.get(); + }, + name: function () { + return name.get(); + } + }); + + // Check that the id and value attribute are as we expect. + // We can't check div.innerHTML because Chrome at least doesn't + // appear to put textarea value attributes in innerHTML. + var textarea = div.querySelector("textarea"); + test.equal(textarea.id, attrs.get().id); + test.equal( + textarea.value, tmplInfo.hasTextAreaContents ? "Hello one" : ""); + // One of the templates has a separate attribute in addition to + // an attributes dictionary. + if (tmplInfo === tmplWithContentsAndMoreAttrs) { + test.equal($(textarea).attr("class"), "bar"); + } + + // Change the id, check that the attribute updates reactively. + attrs.set({ id: "textarea-" + Random.id() }); + Tracker.flush(); + test.equal(textarea.id, attrs.get().id); + + // Change the name variable, check that the textarea value + // updates reactively. + name.set("two"); + Tracker.flush(); + test.equal( + textarea.value, tmplInfo.hasTextAreaContents ? "Hello two" : ""); + + if (tmplInfo === tmplWithContentsAndMoreAttrs) { + test.equal($(textarea).attr("class"), "bar"); + } + + }); + + }); + +Tinytest.add( + "spacebars-tests - old - template_tests - this.autorun", + function (test) { + var tmpl = Template.old_spacebars_test_autorun; + var tmplInner = Template.old_spacebars_test_autorun_inner; + + // Keep track of the value of `Template.instance()` inside the + // autorun each time it runs. + var autorunTemplateInstances = []; + var actualTemplateInstance; + var returnedComputation; + var computationArg; + + var show = new ReactiveVar(true); + var rv = new ReactiveVar("foo"); + + tmplInner.created = function () { + actualTemplateInstance = this; + returnedComputation = this.autorun(function (c) { + computationArg = c; + rv.get(); + autorunTemplateInstances.push(Template.instance()); + }); + }; + + tmpl.helpers({ + show: function () { + return show.get(); + } + }); + + var div = renderToDiv(tmpl); + test.equal(autorunTemplateInstances.length, 1); + test.equal(autorunTemplateInstances[0], actualTemplateInstance); + + // Test that the autorun returned a computation and received a + // computation as an argument. + test.isTrue(returnedComputation instanceof Tracker.Computation); + test.equal(returnedComputation, computationArg); + + // Make sure the autorun re-runs when `rv` changes, and that it has + // the correct current view. + rv.set("bar"); + Tracker.flush(); + test.equal(autorunTemplateInstances.length, 2); + test.equal(autorunTemplateInstances[1], actualTemplateInstance); + + // If the inner template is destroyed, the autorun should be stopped. + show.set(false); + Tracker.flush(); + rv.set("baz"); + Tracker.flush(); + + test.equal(autorunTemplateInstances.length, 2); + test.equal(rv._numListeners(), 0); + } +); + +// Test that argument in {{> UI.contentBlock arg}} is evaluated in +// the proper data context. +Tinytest.add( + "spacebars-tests - old - template_tests - contentBlock argument", + function (test) { + var tmpl = Template.old_spacebars_test_contentBlock_arg; + var div = renderToDiv(tmpl); + test.equal(canonicalizeHtml(div.innerHTML), 'AAA BBB'); + }); + +// Test that when Blaze sets an input field to the same value, +// we don't lose the insertion point position. +Tinytest.add( + "spacebars-tests - old - template_tests - input field to same value", + function (test) { + var tmpl = Template.old_spacebars_template_test_input_field_to_same_value; + var R = ReactiveVar("BLAH"); + tmpl.foo = function () { return R.get(); }; + var div = renderToDiv(tmpl); + + document.body.appendChild(div); + + var input = div.querySelector('input'); + test.equal(input.value, "BLAH"); + + var setSelection = function (startEnd) { + startEnd = startEnd.split(' '); + if (typeof input.selectionStart === 'number') { + // all but IE < 9 + input.selectionStart = startEnd[0]; + input.selectionEnd = startEnd[1]; + } else { + // IE 8 + input.focus(); + var r = input.createTextRange(); + // move the start and end of the range to the beginning + // of the input field + r.moveStart('textedit', -1); + r.moveEnd('textedit', -1); + // move the start and end a certain number of characters + // (relative to their current position) + r.moveEnd('character', startEnd[1]); + r.moveStart('character', startEnd[0]); + r.select(); + } + }; + var getSelection = function () { + if (typeof input.selectionStart === 'number') { + // all but IE < 9 + return input.selectionStart + " " + input.selectionEnd; + } else { + // IE 8 + input.focus(); + var r = document.selection.createRange(); + var fullText = input.value; + var start, end; + if (r.text) { + // one or more characters are selected. + // this is kind of hacky! Relies on fullText + // not having duplicate letters, for example. + start = fullText.indexOf(r.text); + end = start + r.text.length; + } else { + r.moveStart('textedit', -1); + start = end = r.text.length; + } + return start + " " + end; + } + }; + + setSelection("2 3"); + test.equal(getSelection(), "2 3"); + // At this point, we COULD confirm that setting input.value to + // the same thing as before ("BLAH") loses the insertion + // point (per browser behavior). However, it doesn't on Firefox. + // So we set it to something different, which verifies that our + // test machinery is correct. + input.value = "BLAN"; + // test that insertion point is lost + var selectionAfterSet = getSelection(); + if (selectionAfterSet !== "0 0") // IE 8 + test.equal(getSelection(), "4 4"); + + // now make the input say "BLAH" but the AttributeHandler + // says "OTHER" (so we can make it do the no-op update) + R.set("OTHER"); + Tracker.flush(); + test.equal(input.value, "OTHER"); + input.value = "BLAH"; + setSelection("2 2"); + + R.set("BLAH"); + Tracker.flush(); + test.equal(input.value, "BLAH"); + // test that didn't lose insertion point! + test.equal(getSelection(), "2 2"); + + // clean up after ourselves + document.body.removeChild(div); + } +); + diff --git a/packages/spacebars-tests/package.js b/packages/spacebars-tests/package.js index 9325998b6e..d12ad035aa 100644 --- a/packages/spacebars-tests/package.js +++ b/packages/spacebars-tests/package.js @@ -21,7 +21,10 @@ Package.on_test(function (api) { 'template_tests.html', 'template_tests.js', 'templating_tests.html', - 'templating_tests.js' + 'templating_tests.js', + + 'old_templates.js', // backcompat for packages built with old Blaze APIs. + 'old_templates_tests.js' ], 'client'); api.add_files('template_tests_server.js', 'server'); diff --git a/packages/spacebars/package.js b/packages/spacebars/package.js index ddccc7ba6c..f60e899c77 100644 --- a/packages/spacebars/package.js +++ b/packages/spacebars/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Handlebars-like template language for Meteor", - version: '1.0.1-rc1' + version: '1.0.1' }); // For more, see package `spacebars-compiler`, which is used by diff --git a/packages/spiderable/package.js b/packages/spiderable/package.js index be6a03e21f..d1d8d61736 100644 --- a/packages/spiderable/package.js +++ b/packages/spiderable/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Makes the application crawlable to web spiders", - version: "1.0.3-rc0" + version: "1.0.3" }); Package.on_use(function (api) { diff --git a/packages/standard-app-packages/package.js b/packages/standard-app-packages/package.js index ea977e7263..248fd35b13 100644 --- a/packages/standard-app-packages/package.js +++ b/packages/standard-app-packages/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Moved to meteor-platform", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/test-helpers/package.js b/packages/test-helpers/package.js index dca8ec1e3a..e6f60fbb19 100644 --- a/packages/test-helpers/package.js +++ b/packages/test-helpers/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Utility functions for tests", - version: '1.0.1-rc1' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/test-in-browser/package.js b/packages/test-in-browser/package.js index 07811ef47e..8853b6c222 100644 --- a/packages/test-in-browser/package.js +++ b/packages/test-in-browser/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Run tests interactively in the browser", - version: '1.0.4-rc1' + version: '1.0.4' }); Package.on_use(function (api) { diff --git a/packages/test-in-console/package.js b/packages/test-in-console/package.js index 1526890bfd..3dc96446a2 100644 --- a/packages/test-in-console/package.js +++ b/packages/test-in-console/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Run tests noninteractively, with results going to the console.", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/tinytest/package.js b/packages/tinytest/package.js index 8588004546..39fae35164 100644 --- a/packages/tinytest/package.js +++ b/packages/tinytest/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Tiny testing framework", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/packages/tracker/package.js b/packages/tracker/package.js index c9a828ca80..406d962231 100644 --- a/packages/tracker/package.js +++ b/packages/tracker/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Dependency tracker to allow reactive callbacks", - version: '1.0.2-rc1' + version: '1.0.2' }); Package.on_use(function (api) { diff --git a/packages/ui/package.js b/packages/ui/package.js index 6b8e51c572..4614bed0a0 100644 --- a/packages/ui/package.js +++ b/packages/ui/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Deprecated: Use the Blaze package", - version: '1.0.1-rc0' + version: '1.0.1' }); Package.on_use(function (api) { diff --git a/scripts/admin/banners.json b/scripts/admin/banners.json index 541ea4c835..ff6aff9c85 100644 --- a/scripts/admin/banners.json +++ b/scripts/admin/banners.json @@ -1,9 +1,9 @@ { "track": "METEOR", "banners": [ { - "versions": ["0.9.0"], + "versions": ["0.9.0", "0.9.0.1"], "banner": { - "text": "=> Meteor 0.9.0.1 is now out, fixing several bugs in 0.9.0.\n\n Meteor 0.9.0.1 is being downloaded in the background. You can update to\n it by running 'meteor update --patch'." + "text": "=> Meteor 0.9.1 is out, adding support for organizations in Meteor\n developer accounts.\n\n Meteor 0.9.1 is being downloading in the background. You can update\n to it by running 'meteor update'." } } ] diff --git a/scripts/admin/manifest.json b/scripts/admin/manifest.json index 92d8bbb80f..68d6162711 100644 --- a/scripts/admin/manifest.json +++ b/scripts/admin/manifest.json @@ -1,7 +1,7 @@ { "releases": { "stable": { - "version": "0.9.0.1", + "version": "0.9.1", "banner": "=> Meteor 0.9.0: Introducing the official Meteor package system,\n including Isobuild and the Meteor Package Server!\n\n Starting in 0.9.0, you can publish your own packages and use any of\n the over 1800 community packages in your app, without needing an\n external tool such as Meteorite. Just use commands like 'meteor add\n ', 'meteor publish', and 'meteor search '.\n\n This release is being downloaded in the background. It's a big\n change! Once it's done downloading, then the next time you run\n 'meteor', your Meteor install will be automatically upgraded to the\n new system. The upgrade will take a few minutes and as part of it\n old versions of Meteor will be removed from your machine. These old\n versions will be automatically redownloaded using the new system if\n you work on apps that use them.\n" } } diff --git a/scripts/admin/meteor-release-official.json b/scripts/admin/meteor-release-official.json index c53290ce2a..b5d65e213d 100644 --- a/scripts/admin/meteor-release-official.json +++ b/scripts/admin/meteor-release-official.json @@ -1,8 +1,7 @@ { "track": "METEOR", - "version": "0.9.0.1", + "version": "0.9.1", "recommended": false, "official": true, - "description": "The official Meteor Distribution", - "patchFrom": ["0.9.0"] + "description": "The official Meteor Distribution" } diff --git a/tools/help.txt b/tools/help.txt index f342072015..06394f7689 100644 --- a/tools/help.txt +++ b/tools/help.txt @@ -128,7 +128,7 @@ Usage: meteor add [package] [package..] Adds packages to your Meteor project. You can add multiple packages with one command. To query for available packages, use -the meteor --search command. +the meteor search command. >>> remove @@ -272,26 +272,26 @@ Retrieves the server logs for the requested site. >>> authorized -View or change authorized users for a site. +View or change authorized users and organizations for a site Usage: meteor authorized [--list] meteor authorized --add meteor authorized --remove -Without an argument (or with --list), list the users that are +Without an argument (or with --list), list the users and organizations that are administrators for a particular site that was deployed with 'meteor deploy' -With --add, add an authorized user to a site. Use this to give your -collaborators the ability to work with your sites. +With --add, add an authorized user or organization to a site. Use this to give +your collaborators the ability to work with your sites. -With --remove, remove an authorized user from a site. You cannot remove -yourself. (Ask someone else who is an authorized user to do it.) +With --remove, remove an authorized user or organization from a site. You cannot +remove yourself. (Ask someone else who is an authorized user to do it.) You can only add or remove one authorized user at a time. Options: - --add add an authorized user - --remove remove an authorized user - --list list authorized users (the default) + --add add an authorized user or organization + --remove remove an authorized user or organization + --list list authorized users and organizations (the default) >>> claim @@ -582,12 +582,12 @@ Options: >>> admin maintainers -View or change authorized maintainers for a package. +View or change package maintainers Usage: meteor admin maintainers [--list] meteor admin maintainers --add meteor admin maintainers --remove -Without an argument (or with --list), list the users that are +Without options (or with --list), list the users and organizations that are maintainers for a particular package. With --add, add an authorized maintainer to a package. Use this to give your @@ -633,3 +633,23 @@ Usage: meteor admin set-banners Set the banners on previously published releases. Banners notify the user when there is a new release available or a patch release has been published. + +>>> admin list-organizations +List the organizations of which you are a member. +Usage: meteor list-organizations + +List the organizations of which you are a member. + +>>> admin members +View or change the members of an organization. +Usage: meteor admin members [--list] + meteor admin members --add + meteor admin members --remove + +Without options, list the members of an organization. With --add or --remove, +add or remove a member of an organization. + +Options: + --add add a member to the organization + --remove remove a member from the organization + --list list members of the organization (the default) diff --git a/tools/main.js b/tools/main.js index 4c91a07420..0b7ec77247 100644 --- a/tools/main.js +++ b/tools/main.js @@ -249,11 +249,19 @@ var longHelp = exports.longHelp = function (commandName) { }); var help = loadHelp(); + + // can use to see if there is help text for a particular command + var helpDict = {}; + _.each(help, function (helpEntry) { + helpDict[helpEntry.name] = helpEntry; + }); + var commandList = null; if (! (node instanceof Command)) { commandList = ''; var items = []; var commandsWanted = {}; + _.each(node, function (n, shortName) { var fullName = commandName + (commandName.length > 0 ? " " : "") + shortName; @@ -262,9 +270,13 @@ var longHelp = exports.longHelp = function (commandName) { // not appear in the top-level help. If we one day want to make // these kinds of commands visible to casual users, we'll need a // way to mark them as visible or hidden. - if (n instanceof Command && ! n.hidden) + + // Also, use helpDict to only include commands that have help text, + // otherwise there is nothing to display + if (n instanceof Command && ! n.hidden && helpDict[fullName]) commandsWanted[fullName] = { name: shortName }; }); + var maxNameLength = _.max(_.map(commandsWanted, function (c) { return c.name.length; })); diff --git a/tools/upgraders.js b/tools/upgraders.js index b2e4cb1e43..e03479c6bf 100644 --- a/tools/upgraders.js +++ b/tools/upgraders.js @@ -55,6 +55,16 @@ var upgradersByName = { // " Accounts UI has totally changed, yo."); // } console.log(); + }, + + "notices-for-0.9.1": function () { + maybePrintNoticeHeader(); + console.log( +"Meteor 0.9.1 includes changes to the Blaze API, in preparation for 1.0.\n" + +"Many previously undocumented APIs are now public and documented. Most changes\n" + +"are backwards compatible, except that templates can no longer be named \"body\"\n" + +"or \"instance\".\n"); + console.log(); } };