mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'devel' into feature/package-deprecation
This commit is contained in:
@@ -93,8 +93,8 @@ build_machine_environment: &build_machine_environment
|
||||
SELF_TEST_TOOL_NODE_FLAGS: " "
|
||||
|
||||
# Variables for load-balancing
|
||||
NUM_GROUPS: 11
|
||||
RUNNING_AVG_LENGTH: 5
|
||||
NUM_GROUPS: 12
|
||||
RUNNING_AVG_LENGTH: 6
|
||||
|
||||
jobs:
|
||||
Get Ready:
|
||||
@@ -153,8 +153,8 @@ jobs:
|
||||
../meteor npx tsc --noEmit
|
||||
popd
|
||||
./meteor --get-ready
|
||||
# shouldn't take longer than 20 minutes
|
||||
no_output_timeout: 20m
|
||||
# shouldn't take longer than 60 minutes
|
||||
no_output_timeout: 60m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- persist_to_workspace:
|
||||
@@ -647,6 +647,211 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Browserstack 1:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
name: "Running self-test (Test Browserstack 1)"
|
||||
command: |
|
||||
TEST_GROUP='css hot code push';
|
||||
echo $TEST_GROUP;
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
./meteor self-test \
|
||||
"$TEST_GROUP" \
|
||||
--browserstack \
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--exclude "${SELF_TEST_EXCLUDE}" \
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/bs1.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 40m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
path: ./tmp/results
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: ./tmp/results/junit
|
||||
- store_artifacts:
|
||||
path: ./tmp/results
|
||||
- store_artifacts:
|
||||
path: /tmp/core_dumps
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Browserstack 2:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
name: "Running self-test (Test Browserstack 2)"
|
||||
command: |
|
||||
TEST_GROUP='custom minifier - devel vs prod';
|
||||
echo $TEST_GROUP;
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
./meteor self-test \
|
||||
"$TEST_GROUP" \
|
||||
--browserstack \
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--exclude "${SELF_TEST_EXCLUDE}" \
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/bs2.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 40m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
path: ./tmp/results
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: ./tmp/results/junit
|
||||
- store_artifacts:
|
||||
path: ./tmp/results
|
||||
- store_artifacts:
|
||||
path: /tmp/core_dumps
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Browserstack 3:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
name: "Running self-test (Test Browserstack 3)"
|
||||
command: |
|
||||
TEST_GROUP='versioning hot code push';
|
||||
echo $TEST_GROUP;
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
./meteor self-test \
|
||||
"$TEST_GROUP" \
|
||||
--browserstack \
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--exclude "${SELF_TEST_EXCLUDE}" \
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/bs3.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 40m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
path: ./tmp/results
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: ./tmp/results/junit
|
||||
- store_artifacts:
|
||||
path: ./tmp/results
|
||||
- store_artifacts:
|
||||
path: /tmp/core_dumps
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Browserstack 4:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
name: "Running self-test (Test Browserstack 4)"
|
||||
command: |
|
||||
TEST_GROUP='javascript hot code push';
|
||||
echo $TEST_GROUP;
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
./meteor self-test \
|
||||
"$TEST_GROUP" \
|
||||
--browserstack \
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--exclude "${SELF_TEST_EXCLUDE}" \
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/bs4.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 40m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
path: ./tmp/results
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: ./tmp/results/junit
|
||||
- store_artifacts:
|
||||
path: ./tmp/results
|
||||
- store_artifacts:
|
||||
path: /tmp/core_dumps
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
Test Browserstack 5:
|
||||
<<: *build_machine_environment
|
||||
steps:
|
||||
- run:
|
||||
<<: *run_log_mem_use
|
||||
- run:
|
||||
<<: *run_env_change
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: "Print environment"
|
||||
command: printenv
|
||||
- run:
|
||||
name: "Running self-test (Test Browserstack 5)"
|
||||
command: |
|
||||
TEST_GROUP='add packages client archs';
|
||||
echo $TEST_GROUP;
|
||||
eval $PRE_TEST_COMMANDS;
|
||||
./meteor self-test \
|
||||
"$TEST_GROUP" \
|
||||
--browserstack \
|
||||
--retries ${METEOR_SELF_TEST_RETRIES} \
|
||||
--exclude "${SELF_TEST_EXCLUDE}" \
|
||||
--headless \
|
||||
--junit ./tmp/results/junit/bs5.xml \
|
||||
--without-tag "custom-warehouse"
|
||||
no_output_timeout: 40m
|
||||
- run:
|
||||
<<: *run_save_node_bin
|
||||
- store_test_results:
|
||||
path: ./tmp/results
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths: ./tmp/results/junit
|
||||
- store_artifacts:
|
||||
path: ./tmp/results
|
||||
- store_artifacts:
|
||||
path: /tmp/core_dumps
|
||||
- store_artifacts:
|
||||
path: /tmp/memuse.txt
|
||||
|
||||
# Test the JSDoc declarations which live within this codebase against the
|
||||
# Meteor Docs (https://github.com/meteor/docs) repository, where they'll
|
||||
# eventually be consumed. This test aims to provide an early warning of
|
||||
@@ -803,6 +1008,21 @@ workflows:
|
||||
- Test Group 10:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Browserstack 1:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Browserstack 2:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Browserstack 3:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Browserstack 4:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Test Browserstack 5:
|
||||
requires:
|
||||
- Get Ready
|
||||
- Clean Up:
|
||||
requires:
|
||||
- Isolated Tests
|
||||
@@ -817,3 +1037,8 @@ workflows:
|
||||
- Test Group 8
|
||||
- Test Group 9
|
||||
- Test Group 10
|
||||
- Test Browserstack 1
|
||||
- Test Browserstack 2
|
||||
- Test Browserstack 3
|
||||
- Test Browserstack 4
|
||||
- Test Browserstack 5
|
||||
|
||||
@@ -90,7 +90,7 @@ tools/isobuild/js-analyze.js
|
||||
tools/isobuild/linker.js
|
||||
tools/isobuild/linter-plugin.js
|
||||
tools/isobuild/meteor-npm.js
|
||||
tools/isobuild/npm-discards.js
|
||||
tools/isobuild/npm-discards.ts
|
||||
tools/isobuild/package-api.js
|
||||
tools/isobuild/package-source.js
|
||||
tools/isobuild/source-arch.js
|
||||
|
||||
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
* ❓ Questions?
|
||||
Use Stack Overflow (http://stackoverflow.com/questions/tagged/meteor), start a discussion on the Meteor forums (https://forums.meteor.com/) or post a message on (Community Slack)[https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc]
|
||||
Start a discussion on the Meteor forums (https://forums.meteor.com/) or post a message on (Community Slack)[https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc]
|
||||
* 💡 Feature requests?
|
||||
Visit the feature request repository (https://github.com/meteor/meteor-feature-requests).
|
||||
* ❗️ Bug?
|
||||
|
||||
16
.github/stale.yml
vendored
16
.github/stale.yml
vendored
@@ -1,16 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
daysUntilStale: 32
|
||||
daysUntilClose: 8
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- confirmed
|
||||
staleLabel: stale-bot
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
closeComment: >
|
||||
This issue has been automatically closed it has not had recent activity.
|
||||
only: issues
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -24,3 +24,9 @@ npm-debug.log
|
||||
universe
|
||||
.babel-cache
|
||||
mongo-test-output
|
||||
|
||||
# core packages shouldn't have .versions files
|
||||
packages/*/.versions
|
||||
|
||||
# packages shouldn't have .npm on Git
|
||||
packages/**/.npm
|
||||
|
||||
@@ -6,6 +6,8 @@ We are excited to have your help building Meteor — both the platform and t
|
||||
|
||||
Before we jump into detailed guidelines for opening and triaging issues and submitting pull requests, here is some information about how our project is structured and resources you should refer to as you start contributing.
|
||||
|
||||
Also, please take a few minutes to understand a few terms in Meteor context reading our [Glossary](GLOSSARY.md).
|
||||
|
||||
### Ways to contribute
|
||||
|
||||
There are many ways to contribute to the Meteor Project. Here’s a list of technical contributions with increasing levels of involvement and required knowledge of Meteor’s code and operations.
|
||||
@@ -23,23 +25,21 @@ If you can think of any changes to the project, [documentation](https://github.c
|
||||
|
||||
### Finding work
|
||||
|
||||
Are you new here? Please check our issues `good-for-first-contribution`: [core](https://github.com/meteor/meteor/labels/good-for-first-contribution), [docs](https://github.com/meteor/docs/labels/good-for-first-contribution), [guide](https://github.com/meteor/guide/labels/good-for-first-contribution).
|
||||
Are you new here? Please check our issues `good-first-issue`: [core](https://github.com/meteor/meteor/labels/good%20first%20issue), [docs](https://github.com/meteor/docs/labels/good%20first%20issue), [guide](https://github.com/meteor/guide/labels/good%20first%20issue).
|
||||
|
||||
We curate specific issues that would make great pull requests for community contributors by applying the `pull-requests-encouraged` label ([bugs](https://github.com/meteor/meteor/issues?q=is%3Aopen+is%3Aissue+label%3Apull-requests-encouraged) / [feature requests](https://github.com/meteor/meteor-feature-requests/issues?q=is%3Aopen+is%3Aissue+label%3Apull-requests-encouraged)).
|
||||
We curate specific issues that would make great pull requests for community contributors by applying the `ready` label.
|
||||
|
||||
Issues which *also* have the `confirmed` label ([bugs](https://github.com/meteor/meteor/issues?q=is%3Aissue%20is%3Aopen%20label%3Apull-requests-encouraged%20label%3Aconfirmed) / [feature requests](https://github.com/meteor/meteor-feature-requests/issues?q=is%3Aissue%20is%3Aopen%20label%3Apull-requests-encouraged%20label%3Aconfirmed)) are considered to have their details clear enough to begin working on.
|
||||
Any issue which does not have the `ready` label still requires discussion on implementation details but input and positive commentary is welcome! Any pull request opened on an issue which is not `confirmed` is still welcome, however the pull-request is more likely to be sent back for reworking than a `ready` issue.
|
||||
|
||||
Any issue which does not have the `confirmed` label still requires discussion on implementation details but input and positive commentary is welcome! Any pull request opened on an issue which is not `confirmed` is still welcome, however the pull-request is more likely to be sent back for reworking than a `confirmed` issue. If in doubt about the best way to implement something, please create additional conversation on the issue. You can also reach Filipe Névola (Meteor Developer Evangelist) and he will help you to find something interesting to work on.
|
||||
|
||||
Please note that `pull-requests-encouraged` issues with low activity will often be closed without being implemented. These issues are tagged with an additional [`not-implemented`](https://github.com/meteor/meteor/issues?utf8=✓&q=label%3Apull-requests-encouraged+label%3Anot-implemented) label, and can still be considered good candidates to work on. If you're interested in working on a closed and `not-implemented` issue, please let us know by posting on that issue.
|
||||
If in doubt about the best way to implement something, please create additional conversation on the issue. You can also reach one of the [core committers](https://github.com/meteor/meteor/blob/devel/CONTRIBUTING.md#core-committer) and they will help you to find something interesting to work on.
|
||||
|
||||
### Project roles
|
||||
|
||||
We’ve just begun to create more defined project roles for Meteor. Here are descriptions of the existing project roles, along with the current contributors taking on those roles today.
|
||||
Here are descriptions of the existing project roles, along with the current contributors taking on those roles today.
|
||||
|
||||
#### Issue Triager
|
||||
|
||||
Issue Triagers are members of the community that meet with us weekly to help triage Meteor’s open issues and bug reports. Once you’ve begun triaging issues regularly on your own, we will invite you to join our dedicated Slack channel to participate in these regular coordination sessions.
|
||||
Issue Triagers are members of the community that help every week with Meteor’s open issues and bug reports.
|
||||
|
||||
Current Issue Triagers:
|
||||
- [meteor](https://github.com/meteor/meteor)
|
||||
@@ -50,50 +50,35 @@ Current Issue Triagers:
|
||||
|
||||
#### Reviewer
|
||||
|
||||
Our most regular and experienced Issue Triagers sometimes move on to doing code reviews for pull requests, and have input into which pull requests should be merged.
|
||||
Reviwers are members of the community that help with Pull Requests reviews.
|
||||
|
||||
Current Reviewers:
|
||||
- [meteor](https://github.com/meteor/meteor)
|
||||
- [@klaussner](https://github.com/klaussner)
|
||||
- [@zodern](https://github.com/zodern)
|
||||
- [@benjamn](https://github.com/benjamn)
|
||||
- [@abernix](https://github.com/abernix)
|
||||
- [@hwillson](https://github.com/hwillson)
|
||||
- [@StorytellerCZ](https://github.com/StorytellerCZ)
|
||||
- [@sebakerckhof](https://github.com/sebakerckhof)
|
||||
- [@filipenevola](https://github.com/filipenevola)
|
||||
- [@renanccastro](https://github.com/renanccastro)
|
||||
|
||||
- [docs](https://github.com/meteor/docs) / [guide](https://github.com/meteor/guide)
|
||||
- [@lorensr](https://github.com/lorensr)
|
||||
- [@filipenevola](https://github.com/filipenevola)
|
||||
- [@renanccastro](https://github.com/renanccastro)
|
||||
|
||||
#### Core Committer
|
||||
|
||||
The contributors with commit access to meteor/meteor are employees of Meteor Software Ltd or community members who have distinguished themselves in other contribution areas. If you want to become a core committer please start writing PRs.
|
||||
|
||||
Current Core Committers:
|
||||
- [@benjamn](https://github.com/benjamn)
|
||||
- [@filipenevola](https://github.com/filipenevola)
|
||||
|
||||
#### Documentation Maintainer
|
||||
|
||||
Documentation Maintainers are regular documentation contributors that have been given the ability to merge docs changes on [meteor/docs](https://github.com/meteor/docs).
|
||||
|
||||
Current Documentation Maintainers:
|
||||
- [@abernix](https://github.com/abernix)
|
||||
- [@lorensr](https://github.com/lorensr)
|
||||
|
||||
#### Community Package Maintainer:
|
||||
|
||||
Community package maintainers are community members who maintain packages outside of Meteor core. This requires code to be extracted from meteor/meteor, and entails a high level of responsibility. For this reason, community maintainers generally (and currently) must first become an advanced contributor to Meteor core and have 4-5 non-trivial pull requests merged that went through the proper contribution work-flow. At that point, core contributors may make the case for breaking out a particular core package, and assist in the technical process around doing so.
|
||||
|
||||
Current Community Package Maintainers:
|
||||
- [@mitar](https://github.com/mitar) for [Blaze](https://github.com/meteor/blaze)
|
||||
- [@renanccastro](https://github.com/renanccastro)
|
||||
- [@denihs](https://github.com/denihs)
|
||||
|
||||
#### Developer Evangelist
|
||||
|
||||
- [@filipenevola](https://github.com/filipenevola) (Feel free to reach him out on [Twitter](https://twitter.com/FilipeNevola))
|
||||
|
||||
[Read more](https://forums.meteor.com/t/im-joining-meteor-as-developer-evangelist/50613/2)
|
||||
|
||||
### Tracking project work
|
||||
|
||||
Right now, the best place to track the work being done on Meteor is to take a look at the latest release milestone [here](https://github.com/meteor/meteor/milestones). Also, the [Meteor Roadmap](Roadmap.md) contains high-level information on the current priorities of the project.
|
||||
@@ -111,8 +96,8 @@ isn't a security risk, please file a report in
|
||||
> will page the security team.
|
||||
|
||||
A Meteor app has many moving parts, and it's often difficult to
|
||||
reproduce a bug based on just a few lines of code. So your report
|
||||
should include a link to a repository with a reproduction. By making it as easy as possible
|
||||
reproduce a bug based on just a few lines of code. So your report
|
||||
should include a link to a repository with a reproduction. By making it as easy as possible
|
||||
for others to reproduce your bug, you make it easier for your bug to be
|
||||
fixed.
|
||||
|
||||
@@ -177,6 +162,8 @@ Finally, you can show your support for (or against!) features by using [GitHub r
|
||||
|
||||
A great way to contribute to Meteor is by helping keep the issues in the repository clean and well organized. This process is called 'issue triage' and the steps are described [here](ISSUE_TRIAGE.md).
|
||||
|
||||
Learn how we use GitHub labels [here](LABELS.md)
|
||||
|
||||
## Documentation
|
||||
|
||||
If you'd like to contribute to Meteor's documentation, head over to https://github.com/meteor/docs or https://github.com/meteor/guide and create issues or pull requests there.
|
||||
@@ -229,13 +216,13 @@ For more information about how to work with Meteor core, take a look at the [Dev
|
||||
|
||||
### Proposing your change
|
||||
|
||||
You'll have the best chance of getting a change into core if you can build consensus in the community for it. Start by creating a well specified feature request as a Github issue, in the [meteor/meteor-feature-requests](https://github.com/meteor/meteor-feature-requests) repository.
|
||||
You'll have the best chance of getting a change into core if you can build consensus in the community for it or if it is listed in the [roadmap](https://github.com/meteor/meteor/blob/devel/Roadmap.md). Start by creating a well specified feature request as a Github issue, in the [meteor/meteor-feature-requests](https://github.com/meteor/meteor-feature-requests) repository.
|
||||
|
||||
Help drive discussion and advocate for your feature on the Github ticket (and perhaps the forums). The higher the demand for the feature and the greater the clarity of it's specification will determine the likelihood of a core contributor prioritizing your feature by flagging it with the `pull-requests-encouraged` label.
|
||||
Help drive discussion and advocate for your feature on the Github ticket (and perhaps the forums). The higher the demand for the feature and the greater the clarity of it's specification will determine the likelihood of a core contributor prioritizing your feature by flagging it with the `ready` label.
|
||||
|
||||
Split features up into smaller, logically separate chunks. It is unlikely that large and complicated PRs will be merged.
|
||||
|
||||
Once your feature has been labelled with `pull-requests-encouraged`, leave a comment letting people know you're working on it and you can begin work on the code.
|
||||
Once your feature has been labelled with `ready`, leave a comment letting people know you're working on it and you can begin work on the code. We have the label `in-development` to track the items in progress.
|
||||
|
||||
### Submitting pull requests
|
||||
|
||||
@@ -244,7 +231,7 @@ Once you've come up with a good design, go ahead and submit a pull request (PR).
|
||||
* Sign the CLA (the bot will ask you do to this in the PR).
|
||||
|
||||
* Base all your work off of the **devel** branch. The **devel** branch
|
||||
is where active development happens. **We do not merge pull requests
|
||||
is where active development happens. **We do not merge pull requests
|
||||
directly into master.**
|
||||
|
||||
* Name your branch to match the feature/bug fix that you are
|
||||
@@ -258,12 +245,14 @@ Once you've come up with a good design, go ahead and submit a pull request (PR).
|
||||
[code contributions](DEVELOPMENT.md#code-style)
|
||||
and
|
||||
[commit messages](DEVELOPMENT.md#commit-messages)
|
||||
|
||||
* Bump the version of the changed package accordingly
|
||||
* If your changes are ok to be released without a whole new Meteor version bump just the patch, for example, 2.4.5 will become 2.4.6.
|
||||
* If your changes need a new Meteor version because they are affecting many parts or they depend on changes in the meteor-tool bump the minor, for example, 2.4.5 will become 2.5.0.
|
||||
* If your change is a major rewrite then bump the major, for example, 2.4.5 will become 3.0.0.
|
||||
* If you bump anything that is not the patch you will need to wait a new Meteor version to have your changes available. This is how Meteor core packages work.
|
||||
|
||||
* Be sure your author field in git is properly filled out with your full name
|
||||
and email address so we can credit you.
|
||||
|
||||
### Need help with your pull request?
|
||||
|
||||
If you need help with a pull request, you should start by asking questions in the issue which it pertains to. If you feel that your pull request is almost ready or needs feedback which can only be demonstrated with code, go ahead and open a pull-request with as much progress as possible. By including a "[Work in Progress]" note in the subject, project contributors will know you need help!
|
||||
|
||||
Submitting a pull request is no guarantee it will be accepted, but contributors will do their best to help move your pull request toward release.
|
||||
* You can submit PRs that are not ready yet, submit them as Draft on GitHub and explain what is left and also if you need help.
|
||||
|
||||
@@ -65,6 +65,7 @@ When `meteor` is run from a checkout, a `dev_bundle` is automatically downloaded
|
||||
* Node.js version
|
||||
* npm version
|
||||
* MongoDB version
|
||||
* TypeScript version
|
||||
* Packages [used by `meteor-tool`](scripts/dev-bundle-tool-package.js)
|
||||
* Packages [used by the server bundle](scripts/dev-bundle-server-package.js)
|
||||
|
||||
@@ -162,6 +163,13 @@ In a similar way to the method of specifying which tests TO run, there is a way
|
||||
|
||||
Simply remove the `--list` flag to actually run the matching tests.
|
||||
|
||||
#### Avoiding retries
|
||||
|
||||
On CI we want to retry the tests to avoid false failures but in development can take some time if you retry every time a test is failing. So to avoid retries use:
|
||||
|
||||
./meteor self-test --retries 0
|
||||
|
||||
|
||||
#### More reading
|
||||
|
||||
For even more details on how to run Meteor Tool "self tests", please refer to the [Testing section of the Meteor Tool README](https://github.com/meteor/meteor/blob/master/tools/README.md#testing).
|
||||
@@ -182,7 +190,7 @@ Since Meteor is a free, open-source project, you can run tests in the context of
|
||||
|
||||
To enable CircleCI for your development:
|
||||
|
||||
1. Make sure you have an account with [CircleCI](https://circleci.com)
|
||||
0. Make sure you have an account with [CircleCI](https://circleci.com)
|
||||
0. Make sure you have [forked](https://help.github.com/articles/fork-a-repo/) [Meteor](https://github.com/meteor/meteor) into your own GitHub account.
|
||||
0. Go to the [Add Projects](https://circleci.com/add-projects) page on CircleCI.
|
||||
0. On the left, click on your GitHub username.
|
||||
@@ -201,7 +209,7 @@ To enable CircleCI for your development:
|
||||
|
||||
## Commit messages
|
||||
|
||||
Good commit messages are very important and you should make sure to explain what is changing and why. The commit message should include:
|
||||
Good commit messages are very important and you should make sure to explain what is changing and why. The commit message should include:
|
||||
|
||||
* A short and helpful commit title (maximum 80 characters).
|
||||
* A commit description which clearly explains the change if it's not super-obvious by the title. Some description always helps!
|
||||
|
||||
42
GLOSSARY.md
Normal file
42
GLOSSARY.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Glossary
|
||||
A list of terms and what they mean in Meteor context. This document is intended for contributors.
|
||||
|
||||
If you are reading Meteor code or Meteor docs anywhere and you find that a term is not clear enough or Meteor has used the term in a way that is not easy to understand please submit a PR adding a new term to this glossary. You don't need to be afraid of being wrong, we will review the PR and we can define the term in the best way possible in the review process.
|
||||
|
||||
## Core package
|
||||
A core package is of course a Meteor package. They are maintained in the official Meteor repo.
|
||||
|
||||
Core packages don't have .versions file as they are always released from a checkout of Meteor.
|
||||
|
||||
Every package that lives exactly in the folder `packages/` in the Meteor repository is considered a core package. If the packages lives in sub-folders of `packages`, like `deprecated` or `non-core` they are not considered a core package.
|
||||
|
||||
## Isobuild
|
||||
Meteor has a packaging system called "Isobuild". Isobuild knows how to compile the same JavaScript code-base to different architectures: browser, node.js-like server environment (could be Rhino or other) or a webview in a Cordova mobile app.
|
||||
|
||||
related terms: [Isopack](#isopack), [Unibuild](#unibuild)
|
||||
|
||||
## Isopack
|
||||
Each package used by Isobuild forms an Isopack. Isopack is a package format containing source code for each architecture it can be ran on. Each separate part built for a separate architecture is called "Unibuild".
|
||||
|
||||
related terms: [Isobuild](#isobuild), [Unibuild](#unibuild)
|
||||
|
||||
## Isopackets
|
||||
Isopacket is a set of isopacks. Isopackets are used only inside meteor-tool.
|
||||
|
||||
An isopacket is a predefined set of isopackages which the meteor command-line tool can load into its process. This is how we use the DDP client and many other packages inside the tool. The isopackets are listed a constant called ISOPACKETS.
|
||||
|
||||
related terms: [Isopack](#isopack), [meteor-tool](#meteor-tool)
|
||||
|
||||
## meteor-tool
|
||||
This is the Meteor command-line tool. Most of the code for it is in the [tools directory](https://github.com/meteor/meteor/tree/devel/tools) of the Meteor repository.
|
||||
|
||||
The Meteor tool also includes testing functionality and example apps for the Meteor framework.
|
||||
|
||||
It also defines the version of Meteor, when we say that you are using Meteor 1.12.1 that means you are using meteor-tool@1.12.1.
|
||||
|
||||
## Unibuild
|
||||
Isopack is a package format containing source code for each architecture it can be ran on. Each separate part built for a separate architecture is called "Unibuild".
|
||||
|
||||
There are multiple reasons why we can't call it just "build" and historically the name "Unibuild" has been associated with parts of Isopacks. We also can't call it "Isobuild" because this is the brand-name of the whole build/packaging system.
|
||||
|
||||
related terms: [Isobuild](#isobuild), [Isopack](#isopack)
|
||||
264
History.md
264
History.md
@@ -1,4 +1,92 @@
|
||||
## vNEXT, unreleased
|
||||
## v2.1, 2021-02-24
|
||||
|
||||
### Changes
|
||||
|
||||
#### Highlights
|
||||
|
||||
- Node.js security [update](https://nodejs.org/en/blog/vulnerability/february-2021-security-releases/) to 12.21.0
|
||||
|
||||
#### Meteor Version Release
|
||||
|
||||
* `meteor-tool@2.1`
|
||||
- Node.js security [update](https://nodejs.org/en/blog/vulnerability/february-2021-security-releases/) to 12.21.0
|
||||
- `meteor create my-app --plan professional` new flag `plan` to enable you to choose a plan from the deploy command.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* N/A
|
||||
|
||||
### Migration steps
|
||||
|
||||
* N/A
|
||||
|
||||
## v2.0, 2021-01-20
|
||||
|
||||
### Changes
|
||||
|
||||
#### Highlights
|
||||
|
||||
- Free deploy on [Cloud](https://www.meteor.com/cloud): Deploy for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy))
|
||||
|
||||
|
||||
- Deploy including MongoDB on [Cloud](https://www.meteor.com/cloud): Deploy including MongoDB in a shared instance for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free --mongo`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy))
|
||||
|
||||
|
||||
- Hot Module Replacement (HMR): Updates the javascript modules in a running app that were modified during a rebuild. Reduces the feedback cycle while developing so you can view and test changes quicker (it even updates the app before the build has finished). Enabled by adding the `hot-module-replacement` package to an app. React components are automatically updated by default using React Fast Refresh. Integrations with other libraries and view layers can be provided by third party packages. Support for Blaze is coming soon. This first version supports app code in the modern web architecture. ([docs](https://guide.meteor.com/build-tool.html#hot-module-replacement)) [#11117](https://github.com/meteor/meteor/pull/11117)
|
||||
|
||||
#### Meteor Version Release
|
||||
|
||||
* `meteor-tool@2.0`
|
||||
- `meteor create my-app` now creates by default a project using React. If you want to create a new project using Blaze you should use the new option `--blaze`.
|
||||
- `meteor create --react my-app` is still going to create a React project.
|
||||
- `meteor create --free` deploy for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy)).
|
||||
- `meteor create --free --mongo` deploy including MongoDB in a shared instance for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free --mongo`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy))
|
||||
- `isobuild` fixes a regression on recompiling node modules in different architectures. [#11290](https://github.com/meteor/meteor/pull/11290)
|
||||
- `isobuild` converts npm-discards.js to TypeScript. [#10663](https://github.com/meteor/meteor/pull/10663)
|
||||
- `cordova` ensures the pathname of the rootUrl is used in the mobile URL. [#11053](hhttps://github.com/meteor/meteor/pull/11053)
|
||||
- Add `file.hmrAvailable()` for compiler plugins to check if a file meets the minimum requirements to be updated with HMR [#11117](https://github.com/meteor/meteor/pull/11117)
|
||||
|
||||
|
||||
* `hot-module-replacement@1.0.0`
|
||||
- New package that enables Hot Module Replacement for the Meteor app and provides an API to configure how updates are applied. HMR reduces the feedback cycle while developing by updating modified javascript modules within the running application. ([docs](https://docs.meteor.com/packages/hot-module-replacement.html)) [#11117](https://github.com/meteor/meteor/pull/11117)
|
||||
- These packages have been updated to support HMR: `autoupdate@1.7.0`, `babel-compiler@7.6.0`, `ddp-client@2.4.0`, `dynamic-import@0.6.0`, `ecmascript@0.15.0`, `modules@0.16.0`, `modules-runtime-hot@0.13.0`, `standard-minifier-css@1.7.2`, `webapp@1.10.0`, `webapp-hashing@1.1.0`
|
||||
|
||||
|
||||
* `react-fast-refresh@0.1.0`
|
||||
- New package that updates React components using HMR. This is enabled by default in apps that have HMR enabled and use a supported React version. ([docs](https://atmospherejs.com/meteor/react-fast-refresh)) [#11117](https://github.com/meteor/meteor/pull/11117)
|
||||
|
||||
|
||||
* `dev-error-overlay@0.1.0`
|
||||
- New package that allows you to see build errors and server crashes in your browser during development. Requires the app to have HMR enabled. [#11117](https://github.com/meteor/meteor/pull/11117)
|
||||
|
||||
|
||||
* `accounts-base@1.8.0` and `accounts-password@1.7.0`
|
||||
- Extra parameters can now be added to reset password, verify e-mail and enroll account links that are generated for account e-mails. By default, these are added as search parameters to the generated url. You can pass them as an object in the appropriate functions. E.g. `Accounts.sendEnrollmentEmail(userId, email, null, extraParams);`. [#11288](https://github.com/meteor/meteor/pull/11288)
|
||||
|
||||
|
||||
* `logging@1.2.0`
|
||||
- Updates dependencies and make debug available for use in non production environments. [#11068](https://github.com/meteor/meteor/pull/11068)
|
||||
|
||||
#### Independent Releases
|
||||
* `react-meteor-data@2.2.0`
|
||||
- Fix issue with useTracker and Subscriptions when using deps. [#306](https://github.com/meteor/react-packages/pull/306)
|
||||
- Remove version constraint on core TypeScript package [#308](https://github.com/meteor/react-packages/pull/308)
|
||||
|
||||
|
||||
* `http`
|
||||
- It has been deprecated. [#11068](https://github.com/meteor/meteor/pull/11068)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* `http` package has been deprecated. Please start on migrating towards the [fetch](https://atmospherejs.com/meteor/fetch) package instead.
|
||||
|
||||
### Migration steps
|
||||
|
||||
Simple run `meteor update` in your app.
|
||||
|
||||
Great new features and no breaking changes (except one package deprecation). You can always check our [Roadmap](./Roadmap.md) to understand what is next.
|
||||
|
||||
## v1.12.1, 2021-01-06
|
||||
|
||||
### Breaking changes
|
||||
|
||||
@@ -10,7 +98,123 @@ N/A
|
||||
|
||||
### Changes
|
||||
|
||||
* `--apollo` skeleton was missing client cache setup [PR #11146](https://github.com/meteor/meteor/pull/11146)
|
||||
#### Highlights
|
||||
|
||||
- Node.js 12.20.1 [release notes](https://nodejs.org/en/blog/vulnerability/january-2021-security-releases/)
|
||||
- Fixes problem on IE because of modern syntax on `dynamic-import` package.
|
||||
|
||||
#### Meteor Version Release
|
||||
|
||||
* `dynamic-import@0.5.5`
|
||||
- Fixes problem on IE because of modern syntax (arrow function).
|
||||
|
||||
* `meteor-babel@7.10.6`
|
||||
- Allows to disable sourceMap generation [#36](https://github.com/meteor/babel/pull/36)
|
||||
|
||||
* `babel-compiler@7.5.5`
|
||||
- Allows to disable sourceMap generation [#36](https://github.com/meteor/babel/pull/36)
|
||||
|
||||
## v1.12, 2020-12-04
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- When importing types, you might need to use the "type" qualifier, like so:
|
||||
```js
|
||||
import { Point } from 'react-easy-crop/types';
|
||||
```
|
||||
to
|
||||
```ts
|
||||
import type { Point } from 'react-easy-crop/types';
|
||||
```
|
||||
Because now emitDecoratorsMetadata is enabled.
|
||||
|
||||
- Refer to typescript breaking changes before migrating your existing project, from 3.7.6 to 4.1.2: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes
|
||||
|
||||
### Migration steps
|
||||
|
||||
N/A
|
||||
|
||||
### Changes
|
||||
|
||||
#### Highlights
|
||||
- TypeScript update from 3.7.6 to 4.1.2.
|
||||
- enables decorators and metadata reflection. Important: these are stage 2 features so be aware that breaking changes could be introduced before they reach stage 3.
|
||||
|
||||
#### Meteor Version Release
|
||||
* `meteor-tool@1.12`
|
||||
- updates TypeScript to 4.1.2. [#11225](https://github.com/meteor/meteor/pull/11225) and [#11255](https://github.com/meteor/meteor/pull/11255)
|
||||
- adds new options for `meteor list` command (TODO pending link to updated doc). [#11165](https://github.com/meteor/meteor/pull/11165)
|
||||
- supports Cordova add plugin command working again with plugin id or plugin name in the git URL as it was before Meteor 1.11. [#11202](https://github.com/meteor/meteor/pull/11202)
|
||||
- avoids MiTM by downloading through https. [#11188](https://github.com/meteor/meteor/pull/11188)
|
||||
|
||||
* `meteor-babel@7.10.5`
|
||||
- updates TypeScript to 4.1.2 and enables decorators and metadata reflection. [#11225](https://github.com/meteor/meteor/pull/11225) and [#11255](https://github.com/meteor/meteor/pull/11255)
|
||||
|
||||
* `minimongo@1.6.1`
|
||||
- fixes a null reference exception, if an array contains null values while compiling a fields projection. [#10499](https://github.com/meteor/meteor/pull/10499).
|
||||
|
||||
* `accounts-password@1.6.3`
|
||||
- adds a new function `createUserVerifyingEmail` (TODO pending link to updated doc). [#11080](https://github.com/meteor/meteor/pull/11080)
|
||||
- fixes a typo. [#11182](https://github.com/meteor/meteor/pull/11182)
|
||||
|
||||
* `browser-content-policy@1.1.1`
|
||||
- adds support to nonce
|
||||
```js
|
||||
BrowserPolicy.content.allowScriptOrigin(`nonce-${nonce}`);
|
||||
```
|
||||
|
||||
* `accounts-ui@1.3.2`
|
||||
- follow accounts-ui-unstyled release
|
||||
|
||||
* `accounts-ui-unstyled@1.4.3`
|
||||
- fixes the login form would send the server two login requests
|
||||
- fixes the "forgot password" form would not only send the email but also refresh the page
|
||||
|
||||
* `dynamic-import@0.5.4`
|
||||
- fixes prefetching errors. [#11209](https://github.com/meteor/meteor/pull/11209)
|
||||
- adds the option for dynamic-imports to fetch from the current origin instead of the absolute URL. [#11105](https://github.com/meteor/meteor/pull/11105)
|
||||
|
||||
* `mongo-decimal@0.1.2`
|
||||
- updates npm dependency `decimal.js` to v10.2.1
|
||||
|
||||
* `accounts-base@1.7.1`
|
||||
- adds the ability to define default user fields published on login. [#11118](https://github.com/meteor/meteor/pull/11118)
|
||||
|
||||
* `standard-minifier-css@1.7.0`
|
||||
- modernize and update dependencies. [#11196](https://github.com/meteor/meteor/pull/11196)
|
||||
|
||||
|
||||
#### Independent Releases
|
||||
* `facebook-oauth@1.7.3`
|
||||
- is now using Facebook GraphAPI v8. [#11160](https://github.com/meteor/meteor/pull/11160)
|
||||
|
||||
## v1.11.1, 2020-09-16
|
||||
|
||||
### Breaking changes
|
||||
|
||||
N/A
|
||||
|
||||
### Migration steps
|
||||
|
||||
N/A
|
||||
|
||||
### Changes
|
||||
|
||||
* `--apollo` skeleton was missing client cache setup [more](https://github.com/meteor/meteor/pull/11146)
|
||||
|
||||
* `--vue` skeleton was updated to use proper folder structure [more](https://github.com/meteor/meteor/pull/11174)
|
||||
|
||||
* All skeletons got their `npm` dependencies updated. [more](https://github.com/meteor/meteor/pull/11172)
|
||||
|
||||
* Node.js has been updated to version [12.18.4](https://nodejs.org/en/blog/release/v12.18.4/), this is a [security release](https://nodejs.org/en/blog/vulnerability/september-2020-security-releases/)
|
||||
|
||||
* Updated npm to version 6.14.8 [more](https://blog.npmjs.org/post/626732790304686080/release-6148)
|
||||
|
||||
* `npm-mongo` version 3.8.1 was published, updating `mongodb` to [3.6.2](https://github.com/mongodb/node-mongodb-native/releases/tag/v3.6.2) [more](https://github.com/advisories/GHSA-pp7h-53gx-mx7r)
|
||||
|
||||
* Updated PostCSS from 7.0.31 to 7.0.32 [more](https://github.com/meteor/meteor/issues/10682)
|
||||
|
||||
* Allow android-webview-video-poster [more](https://github.com/meteor/meteor/pull/11159)
|
||||
|
||||
## v1.11, 2020-08-18
|
||||
|
||||
@@ -21,6 +225,8 @@ N/A
|
||||
instead of `dns.lookup()` which might be breaking on some environments.
|
||||
See [nodemailer changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) for more information.
|
||||
|
||||
* (Added later) Cordova add plugin is not working with plugin name in the git URL when the plugin id was different than the name in the config.xml. Fixed on [#11202](https://github.com/meteor/meteor/pull/11202)
|
||||
|
||||
### Migration steps
|
||||
|
||||
N/A
|
||||
@@ -41,7 +247,7 @@ N/A
|
||||
|
||||
* Node.js has been updated to version
|
||||
[12.18.3](https://nodejs.org/en/blog/release/v12.18.3/)
|
||||
|
||||
|
||||
* Updated npm to version 6.14.5
|
||||
|
||||
* `mongodb` driver npm dependency has been updated to 3.6.0
|
||||
@@ -74,14 +280,14 @@ N/A
|
||||
|
||||
### Changes
|
||||
|
||||
* Adds support to override MongoDB options via Meteor settings. Code PR
|
||||
[#10976](https://github.com/meteor/meteor/pull/10976), Docs PR
|
||||
* Adds support to override MongoDB options via Meteor settings. Code PR
|
||||
[#10976](https://github.com/meteor/meteor/pull/10976), Docs PR
|
||||
[#662](https://github.com/meteor/docs/pull/662)
|
||||
|
||||
* The `meteor-babel` npm package has been updated to version 7.9.0.
|
||||
|
||||
* The `typescript` npm package has been updated to version 3.8.3.
|
||||
|
||||
|
||||
* To pass Node command line flags to the server node instance,
|
||||
now it is recommended to use `SERVER_NODE_OPTIONS` instead of `NODE_OPTIONS`.
|
||||
Since Meteor 0.5.3, Meteor allowed to pass node command line flags via the `NODE_OPTIONS`
|
||||
@@ -94,12 +300,12 @@ N/A
|
||||
* The version of MongoDB used by Meteor in development has been updated from
|
||||
4.2.1 to 4.2.5.
|
||||
[PR #11020](https://github.com/meteor/meteor/pull/11020)
|
||||
|
||||
|
||||
* The `url` package now provides an isomorphic implentation of the [WHATWG `url()`
|
||||
API](https://url.spec.whatwg.org/).
|
||||
While remaining backwards compatible, you can now also import `URL` and `URLSearchParams` from `meteor/url`.
|
||||
These will work for both modern and legacy browsers as well as node.
|
||||
|
||||
|
||||
|
||||
## v1.10.1, 2020-03-12
|
||||
|
||||
@@ -108,15 +314,15 @@ N/A
|
||||
* Cordova has been updated from version 7 to 9. We recommend that you test
|
||||
your features that are taking advantage of Cordova plugins to be sure
|
||||
they are still working as expected.
|
||||
|
||||
* WKWebViewOnly is set by default now as true so if you are relying on
|
||||
|
||||
* WKWebViewOnly is set by default now as true so if you are relying on
|
||||
UIWebView or plugins that are using UIWebView APIs you probably want to
|
||||
set it as false, you can do this by calling
|
||||
`App.setPreference('WKWebViewOnly', false);` in your mobile-config.js. But we
|
||||
don't recommend turning this into false because
|
||||
[Apple have said](https://developer.apple.com/news/?id=12232019b) they are
|
||||
set it as false, you can do this by calling
|
||||
`App.setPreference('WKWebViewOnly', false);` in your mobile-config.js. But we
|
||||
don't recommend turning this into false because
|
||||
[Apple have said](https://developer.apple.com/news/?id=12232019b) they are
|
||||
going to reject apps using UIWebView.
|
||||
|
||||
|
||||
* Because MongoDB since 3.4 no longer supports 32-bit Windows, Meteor 1.10 has
|
||||
also dropped support for 32-bit Windows. In other words, Meteor 1.10 supports
|
||||
64-bit Mac, Windows 64-bit, and Linux 64-bit.
|
||||
@@ -126,7 +332,7 @@ N/A
|
||||
MongoDB, you can either reset your project (`meteor reset`)
|
||||
(if you don't care about your local data)
|
||||
or you will need to update the feature compatibility version of your local MongoDB:
|
||||
|
||||
|
||||
1. Downgrade your app to earlier version of Meteor `meteor update --release 1.9.2`
|
||||
2. Start your application
|
||||
3. While your application is running open a new terminal window, navigate to the
|
||||
@@ -136,7 +342,7 @@ N/A
|
||||
5. If the returned version is less than 4.0 update like this:
|
||||
`db.adminCommand({ setFeatureCompatibilityVersion: "4.2" })`
|
||||
6. You can now stop your app and update to Meteor 1.10.
|
||||
|
||||
|
||||
For more information about this, check out [MongoDB documentation](https://docs.mongodb.com/manual/release-notes/4.2-upgrade-standalone/).
|
||||
|
||||
### Changes
|
||||
@@ -159,18 +365,18 @@ N/A
|
||||
* cordova-ios from 4.5.5 to 5.1.1 [release notes](https://github.com/apache/cordova-ios/blob/master/RELEASENOTES.md)
|
||||
* cordova-plugin-wkwebview-engine from 1.1.4 to 1.2.1 [release notes](https://github.com/apache/cordova-plugin-wkwebview-engine/blob/master/RELEASENOTES.md#121-jul-20-2019)
|
||||
* cordova-plugin-whitelist from 1.3.3 to 1.3.4 [release notes](https://github.com/apache/cordova-plugin-whitelist/blob/master/RELEASENOTES.md#134-jun-19-2019)
|
||||
* cordova-plugin-splashscreen (included by mobile-experience > launch-screen)
|
||||
* cordova-plugin-splashscreen (included by mobile-experience > launch-screen)
|
||||
from 4.1.0 to 5.0.3 [release notes](https://github.com/apache/cordova-plugin-splashscreen/blob/master/RELEASENOTES.md#503-may-09-2019)
|
||||
* cordova-plugin-statusbar (included by mobile-experience > mobile-status-bar)
|
||||
* cordova-plugin-statusbar (included by mobile-experience > mobile-status-bar)
|
||||
from 2.3.0 to 2.4.3 [release notes](https://github.com/apache/cordova-plugin-statusbar/blob/master/RELEASENOTES.md#243-jun-19-2019)
|
||||
* On iOS WKWebViewOnly is set by default now as true.
|
||||
* On iOS the Swift version is now set by default to `5` this change can make
|
||||
your app to produce some warnings if your plugins are using old Swift code.
|
||||
You can override the Swift version using
|
||||
your app to produce some warnings if your plugins are using old Swift code.
|
||||
You can override the Swift version using
|
||||
`App.setPreference('SwiftVersion', 4.2);` but we don't recommend that.
|
||||
|
||||
* New command to ensure that Cordova dependencies are installed. Usage:
|
||||
`meteor ensure-cordova-dependencies`. Meteor handles this automatically but in
|
||||
|
||||
* New command to ensure that Cordova dependencies are installed. Usage:
|
||||
`meteor ensure-cordova-dependencies`. Meteor handles this automatically but in
|
||||
some cases, like running in a CI, is useful to install them in advance.
|
||||
|
||||
* You can now pass an `--exclude-archs` option to the `meteor run` and
|
||||
@@ -181,9 +387,9 @@ N/A
|
||||
excluded architectures during development.
|
||||
[Feature #333](https://github.com/meteor/meteor-feature-requests/issues/333),
|
||||
[PR #10824](https://github.com/meteor/meteor/pull/10824)
|
||||
|
||||
* `meteor create --react app` and `--typescript` now use `useTracker` hook instead of
|
||||
`withTracker` HOC, it also uses `function` components instead of `classes`.
|
||||
|
||||
* `meteor create --react app` and `--typescript` now use `useTracker` hook instead of
|
||||
`withTracker` HOC, it also uses `function` components instead of `classes`.
|
||||
|
||||
## v1.9.3, 2020-03-09
|
||||
|
||||
@@ -196,7 +402,7 @@ N/A
|
||||
### Changes
|
||||
* `mongodb` driver package has been updated
|
||||
from 3.2.7 to 3.5.4 [#10961](https://github.com/meteor/meteor/pull/10961)
|
||||
|
||||
|
||||
## v1.9.2, 2020-02-20
|
||||
|
||||
### Breaking changes
|
||||
@@ -296,7 +502,7 @@ N/A
|
||||
fields. [Issue #10469](https://github.com/meteor/meteor/issues/10469)
|
||||
|
||||
* Lots of internal calls to `Meteor.user()` without field specifiers in `accounts-base` and
|
||||
`accounts-password` packages have been optimized with explicit field selectors to only
|
||||
`accounts-password` packages have been optimized with explicit field selectors to only
|
||||
the fields needed by the functions they are in.
|
||||
[Issue #10469](https://github.com/meteor/meteor/issues/10469)
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
This document describes the process Meteor contributors use to organize issues. We use Github [issues](https://github.com/meteor/meteor/issues) in this repository to track bugs, and [meteor/meteor-feature-requests](https://github.com/meteor/meteor-feature-requests) to track feature requests. Our goal is to maintain a list of issues that are relevant and well-defined (and [labeled](https://github.com/meteor/meteor/labels)) such that a contributor can immediately begin working on the code for a fix or feature request. Contributors who want to dive in and write code aren't likely to prioritize working on issues that are ambiguous and have low impact.
|
||||
|
||||
You can filter issues that are missing triage using this [filter](https://github.com/meteor/meteor/issues?q=is%3Aissue+is%3Aopen+-label%3Aconfirmed+-label%3Anot-ready+-label%3Ain-discussion+-label%3Aneeds-reproduction+-label%3Aready+-label%3Ain-development++-label%3Apending-tests+-label%3Awaiting-feedback): `is:issue is:open -label:confirmed -label:not-ready -label:in-discussion -label:needs-reproduction -label:ready -label:in-development -label:pending-tests -label:waiting-feedback`
|
||||
|
||||
We would love to have more contributors who are willing to help out with triaging issues. You can begin by helping issue requesters create good reproductions and by confirming those reproductions on your own machine. It won't be long before the core maintainers notice your work and ask whether you'd like to be promoted to an issue maintainer.
|
||||
|
||||
- [Issue lifecycle](#issue-lifecycle)
|
||||
@@ -13,7 +15,7 @@ We would love to have more contributors who are willing to help out with triagin
|
||||
- [Impact](#impact)
|
||||
- [Issues ready to claim](#issues-ready-to-claim)
|
||||
|
||||
## Issue lifecycle
|
||||
## Lifecycle
|
||||
|
||||
All issues follow the flow outlined below. Your job as an issue maintainer is to work with the requester and others within the community towards the goal of having an issue either become 'claimable' or closed. Read on for more details on the process.
|
||||
|
||||
@@ -21,78 +23,37 @@ All issues follow the flow outlined below. Your job as an issue maintainer is to
|
||||
|
||||
The first step is in determining whether the issue is a bug, help question or feature request. Read on for more details.
|
||||
|
||||
We have [Stale bot](https://github.com/probot/stale) watching this repository with these [settings](https://github.com/meteor/meteor/blob/devel/.github/stale.yml) and closing stale issues. Issues marked as `confirmed`, `pinned` or `security` are never considered stale.
|
||||
|
||||
### Bugs
|
||||
|
||||
1. Duplicates should be closed and marked as such.
|
||||
2. Add the `bug` label and `Project:*` labels that apply (a best guess on the `Project:` is fine; sometimes it's hard to tell exactly which project the issue falls under).
|
||||
2. Add the `Type:Bug` label and `Project:*` labels that apply (a best guess on the `Project:` is fine; sometimes it's hard to tell exactly which project the issue falls under).
|
||||
3. Bugs should have a high-quality reproduction as described [here](CONTRIBUTING.md#reporting-bug). You may need to help the reporter reduce their bug to a minimal reproduction. Leave the issue open.
|
||||
4. A reproduction should be confirmed by at least one person other than the original reporter. Run the reproduction and validate that the bug exists; then make a note of your findings on the issue. If a reproduction is supplied but doesn't work, add the `can't-reproduce` label and make a comment describing what happened.
|
||||
5. Finally, once you've confirmed the reproduction add the `confirmed` label and [classify](#classification) the issue (removing the `can't-reproduce` label if it exists).
|
||||
|
||||
#### Bug issue lifespan
|
||||
|
||||
To help keep issues in this repository under control, and make sure the most important problems are visible to maintainers, unresolved issues (lacking recent activity) should be closed after a certain amount of time has elapsed.
|
||||
|
||||
##### Issues labelled with `pull-requests-encouraged`
|
||||
|
||||
- Open `pull-requests-encouraged` issues should be closed after one month of inactivity, unless someone has clearly identified that they are interested in working on the issue.
|
||||
- When closing, the `not-implemented` label should be added.
|
||||
- A message similar to the following should be included:
|
||||
|
||||
> While we think resolving this issue would be a great addition to the Meteor project, we're going to close it for now due to inactivity. If anyone comes across this issue in the future, and is interested in working on resolving it, please let us know by posting here and we'll consider re-opening this issue. Thanks!
|
||||
|
||||
##### Issues labelled with `bug` and `confirmed`
|
||||
|
||||
- Open `bug` + `confirmed` issues should be closed after two months of inactivity, unless someone has clearly identified that they are interested in working on the issue.
|
||||
- Triagers should do everything possible to help get `bug` + `confirmed` issues to `pull-requests-encouraged`. This means helping clearly identify where the problem is, pointing towards parts of the codebase that someone might want to look into, documenting what a potential solution looks like, etc.
|
||||
|
||||
##### All other issues
|
||||
|
||||
- All open issues that can’t be labelled as `bug` + `confirmed` and/or `pull-requests-encouraged`, should be closed after one month of inactivity.
|
||||
- Triagers should do everything possible to help get `bug` + `confirmed` issues to `pull-requests-encouraged`.
|
||||
4. A reproduction should be confirmed by at least one person other than the original reporter. Run the reproduction and validate that the bug exists; then make a note of your findings on the issue. If a reproduction is supplied but doesn't work, make a comment describing what happened.
|
||||
5. Finally, add a status label and also classification, read more about labels [here](./LABELS.md).
|
||||
|
||||
### Help questions
|
||||
|
||||
[Stack Overflow](http://stackoverflow.com/questions/tagged/meteor) and our [forums](https://forums.meteor.com/c/help) are the place to ask for help on using the framework. Close issues that are help requests and politely refer the author to the above locations.
|
||||
Our [forums](https://forums.meteor.com/c/help) or Community Slack are the place to ask for help on using the framework. Close issues that are help requests and politely refer the author to the above locations.
|
||||
|
||||
### Feature requests
|
||||
|
||||
1. For reasons described [here](CONTRIBUTING.md#feature-requests), we would prefer features to be built as separate packages. If the feature can clearly be built as a package, explain this to the requester and close the issue.
|
||||
> - If the feature could be built as a package and serves a particular need, encourage the user to contribute it themselves.
|
||||
>- If the underlying issue could be better solved by existing technology, encourage them to seek help in the [forums](https://forums.meteor.com/c/help) or on [Stack Overflow](http://stackoverflow.com/questions/tagged/meteor).
|
||||
>- If the underlying issue could be better solved by existing technology, encourage them to seek help in the [forums](https://forums.meteor.com/c/help).
|
||||
2. If you haven't closed the issue, add `Project:*` labels that apply (a best guess on the `Project:` is fine, sometimes it's hard to tell exactly which project the issue falls under).
|
||||
3. If it's not possible to build the feature as a package (as you identified in step 1), explore whether creating hooks in core would make it possible to do so. If it would, redefine the issue as a request to create those hooks.
|
||||
4. Work with the requester and others in the community to build a clear specification for the feature and update the issue description accordingly.
|
||||
5. Finally, add the `confirmed` label and [classify](#classification) the issue.
|
||||
5. Finally, add a status label and also classification, read more about labels [here](./LABELS.md).
|
||||
|
||||
Core contributors may add the `pull-requests-encouraged` label to feature requests. This indicates the feature is aligned with the project roadmap and a high-quality pull request will almost certainly be merged.
|
||||
### Is it ready?
|
||||
|
||||
<h2 id="classification">Classification</h2>
|
||||
|
||||
Assign a classification (via GH labels) that enables the community to determine how to prioritize which issues to work on. The classification is based on *Severity x Impact* .
|
||||
|
||||
### Severity
|
||||
_[Severity:has-workaround, Severity:production, Severity:blocks-development]_
|
||||
|
||||
- If there is a workaround, apply the `Severity:has-workaround` label.
|
||||
- If the issue affects production apps, apply the `Severity:production` label.
|
||||
- If the issue blocks development (e.g `meteor run` is broken), apply the `Severity:blocks-development` label.
|
||||
|
||||
### Impact
|
||||
_[Impact:few, Impact:some, Impact:most]_
|
||||
|
||||
This is a somewhat subjective label and is interpreted in conjunction with Github's upvotes. As a general guideline:
|
||||
|
||||
- `Impact:few` issues would go unnoticed by almost all users, apart from those using a very niche feature, or a feature in an unusual way.
|
||||
- `Impact:some` issues would impact users using a feature that is commonly but not universally used.
|
||||
- `Impact:most` issues would impact more or less every user of the framework.
|
||||
- If the desired fixed or solution is already clear add the label `ready`.
|
||||
- If discussions are still necessary add the label `in-discussion` and start the discussion.
|
||||
|
||||
## Issues ready to claim
|
||||
|
||||
This state indicates that bugs/feature requests have reached the level of quality
|
||||
required for a contributor to begin writing code against (you can easily filter for [bugs](https://github.com/meteor/meteor/labels/confirmed) or [feature requests](https://github.com/meteor/meteor-feature-requests/labels/confirmed) that are ready to claim, by using the `confirmed` label).
|
||||
required for a contributor to begin writing code against (you can easily filter for [Ready](https://github.com/meteor/meteor/labels/ready))
|
||||
|
||||
Although this should have already been done by this stage, ensure the issue is
|
||||
correctly labeled and the title/description have been updated to reflect an
|
||||
|
||||
62
LABELS.md
Normal file
62
LABELS.md
Normal file
@@ -0,0 +1,62 @@
|
||||
## Labels
|
||||
|
||||
Labels are used to organize our issues and PRs.
|
||||
|
||||
We should change the labels of issues and PRs when its status changes.
|
||||
|
||||
### Status Labels
|
||||
Labels to indicate the status of a specific issue or PR. These are the most important labels as they tell us in which stage a specific item is at the moment at a glance.
|
||||
|
||||
You can filter issues that are missing status labels using this [filter](https://github.com/meteor/meteor/issues?q=is%3Aissue+is%3Aopen+-label%3Aconfirmed+-label%3Anot-ready+-label%3Ain-discussion+-label%3Aneeds-reproduction+-label%3Aready+-label%3Ain-development++-label%3Apending-tests+-label%3Awaiting-feedback): `is:issue is:open -label:confirmed -label:not-ready -label:in-discussion -label:needs-reproduction -label:ready -label:in-development -label:pending-tests -label:waiting-feedback`
|
||||
|
||||
#### Stage 1
|
||||
- `confirmed`: We want to fix or implement it
|
||||
- `not-ready`: Something is missing, we are not able to work on this issue yet
|
||||
- `in-discussion`: We are still discussing how to solve or implement it
|
||||
- `needs-reproduction`: We can't reproduce so it's blocked
|
||||
- `invalid`: We don't need to analyze
|
||||
|
||||
#### Stage 2
|
||||
- `ready`: We've decided how to solve or implement it
|
||||
- `in-development`: We are already working on it
|
||||
|
||||
#### Stage 3
|
||||
- `pending-tests`: Tests are not passing, stuck or we need new tests
|
||||
- `waiting-feedback`: It's implemented but we need feedback that it is working as expected
|
||||
|
||||
### Classification Labels
|
||||
|
||||
Assign a classification (via GH labels) that enables the community to determine how to prioritize which issues to work on. The classification is based on *Severity x Impact* .
|
||||
|
||||
#### Severity
|
||||
_[Severity:has-workaround, Severity:production, Severity:blocks-development]_
|
||||
|
||||
- If there is a workaround, apply the `Severity:has-workaround` label.
|
||||
- If the issue affects production apps, apply the `Severity:production` label.
|
||||
- If the issue blocks development (e.g `meteor run` is broken), apply the `Severity:blocks-development` label.
|
||||
|
||||
#### Impact
|
||||
_[Impact:few, Impact:some, Impact:most]_
|
||||
|
||||
This is a somewhat subjective label and is interpreted in conjunction with Github's upvotes. As a general guideline:
|
||||
|
||||
- `Impact:few` issues would go unnoticed by almost all users, apart from those using a very niche feature, or a feature in an unusual way.
|
||||
- `Impact:some` issues would impact users using a feature that is commonly but not universally used.
|
||||
- `Impact:most` issues would impact more or less every user of the framework.
|
||||
|
||||
#### Type
|
||||
_[Type:Bug, Type:Feature]_
|
||||
|
||||
As a general guideline:
|
||||
|
||||
- `Type:Bug` a problem is happening because of an issue in Meteor code.
|
||||
- `Type:Feature` a new behavior or functionality is desired.
|
||||
|
||||
## Project Labels
|
||||
|
||||
They start with `Project:` and they are used to inform the parts of Meteor that are involved in this item.
|
||||
|
||||
## Special Labels
|
||||
|
||||
- `good-first-issue`: Used to indicate items friendly to beginners in Meteor
|
||||
- `hacktoberfest-accepted`: Used to indicate items accepted for [Hacktoberfest](https://hacktoberfest.digitalocean.com/hacktoberfest-update)
|
||||
@@ -12,248 +12,560 @@ MongoDB: http://www.mongodb.org/
|
||||
|
||||
LICENSE
|
||||
|
||||
Most MongoDB source files are made available under the terms of the
|
||||
GNU Affero General Public License (AGPL). See individual files for
|
||||
details.
|
||||
Server Side Public License
|
||||
VERSION 1, OCTOBER 16, 2018
|
||||
|
||||
As an exception, the files in the client/, debian/, rpm/,
|
||||
utils/mongoutils, and all subdirectories thereof are made available under
|
||||
the terms of the Apache License, version 2.0.
|
||||
Copyright © 2018 MongoDB, Inc.
|
||||
|
||||
http://www.gnu.org/licenses/agpl-3.0.html
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
MongoDB uses third-party libraries or other resources that may
|
||||
be distributed under licenses different than the MongoDB software.
|
||||
0. Definitions.
|
||||
|
||||
“This License” refers to Server Side Public License.
|
||||
|
||||
In the event that we accidentally failed to list a required notice,
|
||||
please bring it to our attention through any of the ways detailed here :
|
||||
“Copyright” also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
mongodb-dev@googlegroups.com
|
||||
“The Program” refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as “you”. “Licensees” and
|
||||
“recipients” may be individuals or organizations.
|
||||
|
||||
The attached notices are provided for information only.
|
||||
To “modify” a work means to copy from or adapt all or part of the work in
|
||||
a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a “modified version” of the
|
||||
earlier work or a work “based on” the earlier work.
|
||||
|
||||
A “covered work” means either the unmodified Program or a work based on
|
||||
the Program.
|
||||
|
||||
1) License Notice for Boost
|
||||
---------------------------
|
||||
To “propagate” a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
To “convey” a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through a
|
||||
computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
An interactive user interface displays “Appropriate Legal Notices” to the
|
||||
extent that it includes a convenient and prominently visible feature that
|
||||
(1) displays an appropriate copyright notice, and (2) tells the user that
|
||||
there is no warranty for the work (except to the extent that warranties
|
||||
are provided), that licensees may convey the work under this License, and
|
||||
how to view a copy of this License. If the interface presents a list of
|
||||
user commands or options, such as a menu, a prominent item in the list
|
||||
meets this criterion.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
1. Source Code.
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
The “source code” for a work means the preferred form of the work for
|
||||
making modifications to it. “Object code” means any non-source form of a
|
||||
work.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
A “Standard Interface” means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that is
|
||||
widely used among developers working in that language. The “System
|
||||
Libraries” of an executable work include anything, other than the work as
|
||||
a whole, that (a) is included in the normal form of packaging a Major
|
||||
Component, but which is not part of that Major Component, and (b) serves
|
||||
only to enable use of the work with that Major Component, or to implement
|
||||
a Standard Interface for which an implementation is available to the
|
||||
public in source code form. A “Major Component”, in this context, means a
|
||||
major essential component (kernel, window system, and so on) of the
|
||||
specific operating system (if any) on which the executable work runs, or
|
||||
a compiler used to produce the work, or an object code interpreter used
|
||||
to run it.
|
||||
|
||||
The “Corresponding Source” for a work in object code form means all the
|
||||
source code needed to generate, install, and (for an executable work) run
|
||||
the object code and to modify the work, including scripts to control
|
||||
those activities. However, it does not include the work's System
|
||||
Libraries, or general-purpose tools or generally available free programs
|
||||
which are used unmodified in performing those activities but which are
|
||||
not part of the work. For example, Corresponding Source includes
|
||||
interface definition files associated with source files for the work, and
|
||||
the source code for shared libraries and dynamically linked subprograms
|
||||
that the work is specifically designed to require, such as by intimate
|
||||
data communication or control flow between those subprograms and other
|
||||
parts of the work.
|
||||
|
||||
2) License Notice for V8
|
||||
-------------------------
|
||||
The Corresponding Source need not include anything that users can
|
||||
regenerate automatically from other parts of the Corresponding Source.
|
||||
|
||||
http://code.google.com/p/v8/source/browse/trunk/LICENSE
|
||||
The Corresponding Source for a work in source code form is that same work.
|
||||
|
||||
This license applies to all parts of V8 that are not externally
|
||||
maintained libraries. The externally maintained libraries used by V8
|
||||
are:
|
||||
2. Basic Permissions.
|
||||
|
||||
- Jscre, located under third_party/jscre. This code is copyrighted
|
||||
by the University of Cambridge and Apple Inc. and released under a
|
||||
2-clause BSD license.
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program, subject to section 13. The
|
||||
output from running a covered work is covered by this License only if the
|
||||
output, given its content, constitutes a covered work. This License
|
||||
acknowledges your rights of fair use or other equivalent, as provided by
|
||||
copyright law. Subject to section 13, you may make, run and propagate
|
||||
covered works that you do not convey, without conditions so long as your
|
||||
license otherwise remains in force. You may convey covered works to
|
||||
others for the sole purpose of having them make modifications exclusively
|
||||
for you, or provide you with facilities for running those works, provided
|
||||
that you comply with the terms of this License in conveying all
|
||||
material for which you do not control copyright. Those thus making or
|
||||
running the covered works for you must do so exclusively on your
|
||||
behalf, under your direction and control, on terms that prohibit them
|
||||
from making any copies of your copyrighted material outside their
|
||||
relationship with you.
|
||||
|
||||
- Dtoa, located under third_party/dtoa. This code is copyrighted by
|
||||
David M. Gay and released under an MIT license.
|
||||
Conveying under any other circumstances is permitted solely under the
|
||||
conditions stated below. Sublicensing is not allowed; section 10 makes it
|
||||
unnecessary.
|
||||
|
||||
- Strongtalk assembler, the basis of the files assembler-arm-inl.h,
|
||||
assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
|
||||
assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h.
|
||||
This code is copyrighted by Sun Microsystems Inc. and released
|
||||
under a 3-clause BSD license.
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
These libraries have their own licenses; we recommend you read them,
|
||||
as their terms may differ from the terms below.
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article 11
|
||||
of the WIPO copyright treaty adopted on 20 December 1996, or similar laws
|
||||
prohibiting or restricting circumvention of such measures.
|
||||
|
||||
Copyright 2006-2008, Google 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:
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention is
|
||||
effected by exercising rights under this License with respect to the
|
||||
covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's users,
|
||||
your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
* 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 Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
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.
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice; keep
|
||||
intact all notices stating that this License and any non-permissive terms
|
||||
added in accord with section 7 apply to the code; keep intact all notices
|
||||
of the absence of any warranty; and give all recipients a copy of this
|
||||
License along with the Program. You may charge any price or no price for
|
||||
each copy that you convey, and you may offer support or warranty
|
||||
protection for a fee.
|
||||
|
||||
3) License Notice for PCRE
|
||||
--------------------------
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
http://www.pcre.org/licence.txt
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the terms
|
||||
of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
PCRE LICENCE
|
||||
------------
|
||||
a) The work must carry prominent notices stating that you modified it,
|
||||
and giving a relevant date.
|
||||
|
||||
PCRE is a library of functions to support regular expressions whose syntax
|
||||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
b) The work must carry prominent notices stating that it is released
|
||||
under this License and any conditions added under section 7. This
|
||||
requirement modifies the requirement in section 4 to “keep intact all
|
||||
notices”.
|
||||
|
||||
Release 7 of PCRE is distributed under the terms of the "BSD" licence, as
|
||||
specified below. The documentation for PCRE, supplied in the "doc"
|
||||
directory, is distributed under the same terms as the software itself.
|
||||
c) You must license the entire work, as a whole, under this License to
|
||||
anyone who comes into possession of a copy. This License will therefore
|
||||
apply, along with any applicable section 7 additional terms, to the
|
||||
whole of the work, and all its parts, regardless of how they are
|
||||
packaged. This License gives no permission to license the work in any
|
||||
other way, but it does not invalidate such permission if you have
|
||||
separately received it.
|
||||
|
||||
The basic library functions are written in C and are freestanding. Also
|
||||
included in the distribution is a set of C++ wrapper functions.
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your work
|
||||
need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work, and
|
||||
which are not combined with it such as to form a larger program, in or on
|
||||
a volume of a storage or distribution medium, is called an “aggregate” if
|
||||
the compilation and its resulting copyright are not used to limit the
|
||||
access or legal rights of the compilation's users beyond what the
|
||||
individual works permit. Inclusion of a covered work in an aggregate does
|
||||
not cause this License to apply to the other parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
THE BASIC LIBRARY FUNCTIONS
|
||||
---------------------------
|
||||
You may convey a covered work in object code form under the terms of
|
||||
sections 4 and 5, provided that you also convey the machine-readable
|
||||
Corresponding Source under the terms of this License, in one of these
|
||||
ways:
|
||||
|
||||
Written by: Philip Hazel
|
||||
Email local part: ph10
|
||||
Email domain: cam.ac.uk
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium customarily
|
||||
used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a written
|
||||
offer, valid for at least three years and valid for as long as you
|
||||
offer spare parts or customer support for that product model, to give
|
||||
anyone who possesses the object code either (1) a copy of the
|
||||
Corresponding Source for all the software in the product that is
|
||||
covered by this License, on a durable physical medium customarily used
|
||||
for software interchange, for a price no more than your reasonable cost
|
||||
of physically performing this conveying of source, or (2) access to
|
||||
copy the Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This alternative is
|
||||
allowed only occasionally and noncommercially, and only if you received
|
||||
the object code with such an offer, in accord with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated place
|
||||
(gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to copy
|
||||
the object code is a network server, the Corresponding Source may be on
|
||||
a different server (operated by you or a third party) that supports
|
||||
equivalent copying facilities, provided you maintain clear directions
|
||||
next to the object code saying where to find the Corresponding Source.
|
||||
Regardless of what server hosts the Corresponding Source, you remain
|
||||
obligated to ensure that it is available for as long as needed to
|
||||
satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided you
|
||||
inform other peers where the object code and Corresponding Source of
|
||||
the work are being offered to the general public at no charge under
|
||||
subsection 6d.
|
||||
|
||||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be included
|
||||
in conveying the object code work.
|
||||
|
||||
Copyright (c) 1997-2008 University of Cambridge
|
||||
All rights reserved.
|
||||
A “User Product” is either (1) a “consumer product”, which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, “normally used” refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
“Installation Information” for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
THE C++ WRAPPER FUNCTIONS
|
||||
-------------------------
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as part
|
||||
of a transaction in which the right of possession and use of the User
|
||||
Product is transferred to the recipient in perpetuity or for a fixed term
|
||||
(regardless of how the transaction is characterized), the Corresponding
|
||||
Source conveyed under this section must be accompanied by the
|
||||
Installation Information. But this requirement does not apply if neither
|
||||
you nor any third party retains the ability to install modified object
|
||||
code on the User Product (for example, the work has been installed in
|
||||
ROM).
|
||||
|
||||
Contributed by: Google Inc.
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access
|
||||
to a network may be denied when the modification itself materially
|
||||
and adversely affects the operation of the network or violates the
|
||||
rules and protocols for communication across the network.
|
||||
|
||||
Copyright (c) 2007-2008, Google Inc.
|
||||
All rights reserved.
|
||||
Corresponding Source conveyed, and Installation Information provided, in
|
||||
accord with this section must be in a format that is publicly documented
|
||||
(and with an implementation available to the public in source code form),
|
||||
and must require no special password or key for unpacking, reading or
|
||||
copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
THE "BSD" LICENCE
|
||||
-----------------
|
||||
“Additional permissions” are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall be
|
||||
treated as though they were included in this License, to the extent that
|
||||
they are valid under applicable law. If additional permissions apply only
|
||||
to part of the Program, that part may be used separately under those
|
||||
permissions, but the entire Program remains governed by this License
|
||||
without regard to the additional permissions. When you convey a copy of
|
||||
a covered work, you may at your option remove any additional permissions
|
||||
from that copy, or from any part of it. (Additional permissions may be
|
||||
written to require their own removal in certain cases when you modify the
|
||||
work.) You may place additional permissions on material, added by you to
|
||||
a covered work, for which you have or can give appropriate copyright
|
||||
permission.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
Notwithstanding any other provision of this License, for material you add
|
||||
to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
* 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.
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
* Neither the name of the University of Cambridge nor the name of Google
|
||||
Inc. nor the names of their contributors may be used to endorse or
|
||||
promote products derived from this software without specific prior
|
||||
written permission.
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
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.
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some trade
|
||||
names, trademarks, or service marks; or
|
||||
|
||||
4) License notice for Aladdin MD5
|
||||
---------------------------------
|
||||
f) Requiring indemnification of licensors and authors of that material
|
||||
by anyone who conveys the material (or modified versions of it) with
|
||||
contractual assumptions of liability to the recipient, for any
|
||||
liability that these contractual assumptions directly impose on those
|
||||
licensors and authors.
|
||||
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
All other non-permissive additional terms are considered “further
|
||||
restrictions” within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further restriction,
|
||||
you may remove that term. If a license document contains a further
|
||||
restriction but permits relicensing or conveying under this License, you
|
||||
may add to a covered work material governed by the terms of that license
|
||||
document, provided that the further restriction does not survive such
|
||||
relicensing or conveying.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
If you add terms to a covered work in accord with this section, you must
|
||||
place, in the relevant source files, a statement of the additional terms
|
||||
that apply to those files, or a notice indicating where to find the
|
||||
applicable terms. Additional terms, permissive or non-permissive, may be
|
||||
stated in the form of a separately written license, or stated as
|
||||
exceptions; the above requirements apply either way.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
8. Termination.
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or modify
|
||||
it is void, and will automatically terminate your rights under this
|
||||
License (including any patent licenses granted under the third paragraph
|
||||
of section 11).
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
However, if you cease all violation of this License, then your license
|
||||
from a particular copyright holder is reinstated (a) provisionally,
|
||||
unless and until the copyright holder explicitly and finally terminates
|
||||
your license, and (b) permanently, if the copyright holder fails to
|
||||
notify you of the violation by some reasonable means prior to 60 days
|
||||
after the cessation.
|
||||
|
||||
5) License notice for Snappy - http://code.google.com/p/snappy/
|
||||
---------------------------------
|
||||
Copyright 2005 and onwards Google Inc.
|
||||
Moreover, your license from a particular copyright holder is reinstated
|
||||
permanently if the copyright holder notifies you of the violation by some
|
||||
reasonable means, this is the first time you have received notice of
|
||||
violation of this License (for any work) from that copyright holder, and
|
||||
you cure the violation prior to 30 days after your receipt of the notice.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
* 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 Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
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.
|
||||
You are not required to accept this License in order to receive or run a
|
||||
copy of the Program. Ancillary propagation of a covered work occurring
|
||||
solely as a consequence of using peer-to-peer transmission to receive a
|
||||
copy likewise does not require acceptance. However, nothing other than
|
||||
this License grants you permission to propagate or modify any covered
|
||||
work. These actions infringe copyright if you do not accept this License.
|
||||
Therefore, by modifying or propagating a covered work, you indicate your
|
||||
acceptance of this License to do so.
|
||||
|
||||
A light-weight compression algorithm. It is designed for speed of
|
||||
compression and decompression, rather than for the utmost in space
|
||||
savings.
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
For getting better compression ratios when you are compressing data
|
||||
with long repeated sequences or compressing data that is similar to
|
||||
other data, while still compressing fast, you might look at first
|
||||
using BMDiff and then compressing the output of BMDiff with
|
||||
Snappy.
|
||||
Each time you convey a covered work, the recipient automatically receives
|
||||
a license from the original licensors, to run, modify and propagate that
|
||||
work, subject to this License. You are not responsible for enforcing
|
||||
compliance by third parties with this License.
|
||||
|
||||
An “entity transaction” is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered work
|
||||
results from an entity transaction, each party to that transaction who
|
||||
receives a copy of the work also receives whatever licenses to the work
|
||||
the party's predecessor in interest had or could give under the previous
|
||||
paragraph, plus a right to possession of the Corresponding Source of the
|
||||
work from the predecessor in interest, if the predecessor has it or can
|
||||
get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the rights
|
||||
granted or affirmed under this License. For example, you may not impose a
|
||||
license fee, royalty, or other charge for exercise of rights granted
|
||||
under this License, and you may not initiate litigation (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that any patent claim
|
||||
is infringed by making, using, selling, offering for sale, or importing
|
||||
the Program or any portion of it.
|
||||
|
||||
End
|
||||
11. Patents.
|
||||
|
||||
A “contributor” is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The work
|
||||
thus licensed is called the contributor's “contributor version”.
|
||||
|
||||
A contributor's “essential patent claims” are all patent claims owned or
|
||||
controlled by the contributor, whether already acquired or hereafter
|
||||
acquired, that would be infringed by some manner, permitted by this
|
||||
License, of making, using, or selling its contributor version, but do not
|
||||
include claims that would be infringed only as a consequence of further
|
||||
modification of the contributor version. For purposes of this definition,
|
||||
“control” includes the right to grant patent sublicenses in a manner
|
||||
consistent with the requirements of this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to make,
|
||||
use, sell, offer for sale, import and otherwise run, modify and propagate
|
||||
the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a “patent license” is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To “grant” such a patent license to a party
|
||||
means to make such an agreement or commitment not to enforce a patent
|
||||
against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, and
|
||||
the Corresponding Source of the work is not available for anyone to copy,
|
||||
free of charge and under the terms of this License, through a publicly
|
||||
available network server or other readily accessible means, then you must
|
||||
either (1) cause the Corresponding Source to be so available, or (2)
|
||||
arrange to deprive yourself of the benefit of the patent license for this
|
||||
particular work, or (3) arrange, in a manner consistent with the
|
||||
requirements of this License, to extend the patent license to downstream
|
||||
recipients. “Knowingly relying” means you have actual knowledge that, but
|
||||
for the patent license, your conveying the covered work in a country, or
|
||||
your recipient's use of the covered work in a country, would infringe
|
||||
one or more identifiable patents in that country that you have reason
|
||||
to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties receiving
|
||||
the covered work authorizing them to use, propagate, modify or convey a
|
||||
specific copy of the covered work, then the patent license you grant is
|
||||
automatically extended to all recipients of the covered work and works
|
||||
based on it.
|
||||
|
||||
A patent license is “discriminatory” if it does not include within the
|
||||
scope of its coverage, prohibits the exercise of, or is conditioned on
|
||||
the non-exercise of one or more of the rights that are specifically
|
||||
granted under this License. You may not convey a covered work if you are
|
||||
a party to an arrangement with a third party that is in the business of
|
||||
distributing software, under which you make payment to the third party
|
||||
based on the extent of your activity of conveying the work, and under
|
||||
which the third party grants, to any of the parties who would receive the
|
||||
covered work from you, a discriminatory patent license (a) in connection
|
||||
with copies of the covered work conveyed by you (or copies made from
|
||||
those copies), or (b) primarily for and in connection with specific
|
||||
products or compilations that contain the covered work, unless you
|
||||
entered into that arrangement, or that patent license was granted, prior
|
||||
to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting any
|
||||
implied license or other defenses to infringement that may otherwise be
|
||||
available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot use,
|
||||
propagate or convey a covered work so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations, then
|
||||
as a consequence you may not use, propagate or convey it at all. For
|
||||
example, if you agree to terms that obligate you to collect a royalty for
|
||||
further conveying from those to whom you convey the Program, the only way
|
||||
you could satisfy both those terms and this License would be to refrain
|
||||
entirely from conveying the Program.
|
||||
|
||||
13. Offering the Program as a Service.
|
||||
|
||||
If you make the functionality of the Program or a modified version
|
||||
available to third parties as a service, you must make the Service Source
|
||||
Code available via network download to everyone at no charge, under the
|
||||
terms of this License. Making the functionality of the Program or
|
||||
modified version available to third parties as a service includes,
|
||||
without limitation, enabling third parties to interact with the
|
||||
functionality of the Program or modified version remotely through a
|
||||
computer network, offering a service the value of which entirely or
|
||||
primarily derives from the value of the Program or modified version, or
|
||||
offering a service that accomplishes for users the primary purpose of the
|
||||
Program or modified version.
|
||||
|
||||
“Service Source Code” means the Corresponding Source for the Program or
|
||||
the modified version, and the Corresponding Source for all programs that
|
||||
you use to make the Program or modified version available as a service,
|
||||
including, without limitation, management software, user interfaces,
|
||||
application program interfaces, automation software, monitoring software,
|
||||
backup software, storage software and hosting software, all such that a
|
||||
user could run an instance of the service using the Service Source Code
|
||||
you make available.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
MongoDB, Inc. may publish revised and/or new versions of the Server Side
|
||||
Public License from time to time. Such new versions will be similar in
|
||||
spirit to the present version, but may differ in detail to address new
|
||||
problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies that a certain numbered version of the Server Side Public
|
||||
License “or any later version” applies to it, you have the option of
|
||||
following the terms and conditions either of that numbered version or of
|
||||
any later version published by MongoDB, Inc. If the Program does not
|
||||
specify a version number of the Server Side Public License, you may
|
||||
choose any version ever published by MongoDB, Inc.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of
|
||||
the Server Side Public License can be used, that proxy's public statement
|
||||
of acceptance of a version permanently authorizes you to choose that
|
||||
version for the Program.
|
||||
|
||||
Later license versions may give you additional or different permissions.
|
||||
However, no additional obligations are imposed on any author or copyright
|
||||
holder as a result of your choosing to follow a later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
|
||||
ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
|
||||
THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
|
||||
LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
|
||||
OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided above
|
||||
cannot be given local legal effect according to their terms, reviewing
|
||||
courts shall apply local law that most closely approximates an absolute
|
||||
waiver of all civil liability in connection with the Program, unless a
|
||||
warranty or assumption of liability accompanies a copy of the Program in
|
||||
return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@@ -13,7 +13,7 @@ With Meteor you write apps:
|
||||
* using your choice of popular open-source libraries
|
||||
|
||||
Try a getting started tutorial:
|
||||
* [React](https://www.meteor.com/tutorials/react/creating-an-app)
|
||||
* [React](https://react-tutorial.meteor.com)
|
||||
* [Blaze](https://www.meteor.com/tutorials/blaze/creating-an-app)
|
||||
* [Angular](https://www.meteor.com/tutorials/angular/creating-an-app)
|
||||
* [Vue](https://www.meteor.com/tutorials/vue/creating-an-app)
|
||||
@@ -21,6 +21,8 @@ Try a getting started tutorial:
|
||||
|
||||
Next, read the [guide](https://guide.meteor.com) and the [documentation](https://docs.meteor.com/).
|
||||
|
||||
Are you looking for examples? Check this [meteor/examples](https://github.com/meteor/examples)
|
||||
|
||||
## Quick Start
|
||||
|
||||
On Windows, the installer can be found at https://www.meteor.com/install.
|
||||
@@ -48,9 +50,8 @@ meteor
|
||||
|
||||
Building an application with Meteor?
|
||||
|
||||
* Deploy on Galaxy hosting: https://www.meteor.com/hosting
|
||||
* Deploy on Galaxy hosting: https://www.meteor.com/cloud
|
||||
* Announcement list: sign up at https://www.meteor.com/
|
||||
* Having problems? Ask for help at: https://stackoverflow.com/questions/tagged/meteor
|
||||
* Discussion forums: https://forums.meteor.com/
|
||||
* Join the Meteor community Slack by clicking this [invite link](https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc).
|
||||
|
||||
|
||||
157
Roadmap.md
157
Roadmap.md
@@ -1,6 +1,6 @@
|
||||
# Meteor Roadmap
|
||||
|
||||
**Up to date as of Aug 21, 2020**
|
||||
**Up to date as of Jan 20, 2021**
|
||||
|
||||
This document describes the high-level features and actions for the Meteor project in the near- to medium-term future. This roadmap was built based on community feedback and to improve areas where Meteor is already strong. The description of many items include sentences and ideas from Meteor community members.
|
||||
|
||||
@@ -10,136 +10,65 @@ Contributors are encouraged to focus their efforts on work that aligns with the
|
||||
|
||||
PRs to the roadmap are welcome. If you are willing to contribute please open a PR explaining your ideas and what you would be able to do yourself.
|
||||
|
||||
Ideally, every item in this roadmap should have at least two leaders, leaders are people that are interested in the item and would like to help. If you are interested please open a PR including yourself and describing how do you want to help.
|
||||
## Priorities for V2
|
||||
|
||||
## Core
|
||||
Updated at: 2021/01/20
|
||||
|
||||
### Tree Shaking
|
||||
- Leaders: [Renan Castro](https://github.com/renanccastro) / [Filipe Névola](https://github.com/filipenevola)
|
||||
- Status: In Progress
|
||||
- PRs: [#11107](https://github.com/meteor/meteor/pull/11107)
|
||||
V2 initial release (2.0) was delivered today (2021/01/20) with Hot Module Replacement (HMR), React Fast Refresh, and Free deploy including MongoDB on [Cloud](https://www.meteor.com/cloud) and some other features. See all the changes [here](./History.md).
|
||||
|
||||
Implement tree shaking / dead code elimination, which involves pruning the dependency tree while scanning imports in the `ImportScanner`. We believe it should be possible to treat values like `Meteor.isProduction` and `Meteor.isServer` as constants during this process, and eliminate those branches if their conditions are false (as in https://github.com/meteor/meteor/pull/10056).
|
||||
We expect to have HMR also working for Blaze in Meteor 2.1 in the following weeks (it's currently on [beta](https://github.com/meteor/blaze/pull/313)).
|
||||
|
||||
### Service worker build target
|
||||
- Leaders: <you?>
|
||||
- Status: -
|
||||
- PRs: -
|
||||
Other important updates that you should expect to see in Meteor 2.2, 2.3 and so on:
|
||||
- Node.js 14; [PR](https://github.com/meteor/meteor/pull/11197)
|
||||
- Cordova 10; [PR](https://github.com/meteor/meteor/pull/11208)
|
||||
- Remove deprecated code pre v1; [PR](https://github.com/meteor/meteor/pull/11226)
|
||||
- Tree-shaking; [PR](https://github.com/meteor/meteor/pull/11164)
|
||||
- Blaze HMR; [PR](https://github.com/meteor/blaze/pull/313)
|
||||
- Tutorials migration (help needed, understand [here](https://forums.meteor.com/t/new-meteor-react-tutorial-and-new-format-for-tutorials/54074));
|
||||
|
||||
A proper service worker build target. Regular Web Workers can be built from a function.toString() but service-workers require an actual server route.
|
||||
Do you want to get involved in the items above? Talk to [Filipe Névola](https://twitter.com/filipenevola) in the [community Slack](https://join.slack.com/t/meteor-community/shared_invite/enQtODA0NTU2Nzk5MTA3LWY5NGMxMWRjZDgzYWMyMTEyYTQ3MTcwZmU2YjM5MTY3MjJkZjQ0NWRjOGZlYmIxZjFlYTA5Mjg4OTk3ODRiOTc)
|
||||
|
||||
### Ultra-thin Meteor
|
||||
- Leaders: [Ruither Borba](https://github.com/delki8) / [Christian Klaussner](https://github.com/klaussner)
|
||||
- Status: In Progress
|
||||
- PRs: https://github.com/meteor/meteor/pull/11034 https://github.com/meteor/meteor/pull/11106
|
||||
V2 minor releases are not limited by the items above, these are the ones already in progress, some of them are going to be ready in the next weeks.
|
||||
|
||||
### Page load performance improvements
|
||||
- Leaders: [Seba Kerckhof](https://github.com/sebakerckhof)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
## Priorities for V3
|
||||
|
||||
Make sure we are not delivering any dependency that is not used ([Issue #10701](https://github.com/meteor/meteor/issues/10701), [Issue #10702](https://github.com/meteor/meteor/issues/10702), [Issue #10704](https://github.com/meteor/meteor/issues/10704), [PR #10792](https://github.com/meteor/meteor/pull/10792))
|
||||
Updated at: 2021/01/20
|
||||
|
||||
### Improve Rebuild performance
|
||||
- Leaders: [zodern](https://github.com/zodern) / [Marcelo T Prado](https://github.com/MarceloPrado)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
Meteor is accelerating! We are going release more often this year.
|
||||
|
||||
Explore ideas to improve rebuild time such as split main client bundle into several bundles, split the server bundle into several bundles, store less file content in memory, option to disabling the legacy build (at least in dev mode), etc
|
||||
We expect to have new features focusing in ease app development in V3 or probably in V2 as well, the first step is to review our [feature requests](https://github.com/meteor/meteor-feature-requests) one more time and define new priorities.
|
||||
|
||||
Maybe we should also have a new way of prioritization for new features, right now this [repository]((https://github.com/meteor/meteor-feature-requests)) with issues is not good enough in our opinion, the plan is to be even more open for feedbacks and collaboration. If we make changes in this process we are going to announce in the [Forums](https://forums.meteor.com/) and Slack as always.
|
||||
|
||||
> We are also looking for new developers to be part of our core team and of course if you are already contributing to Meteor you have a head start.
|
||||
>
|
||||
> We don't have an official position description yet but again, contributing to Meteor in the open-source is the best way to join the core team.
|
||||
|
||||
Maybe you are asking: Why the format of this Roadmap was changed in this update?
|
||||
|
||||
We believe the items here were in some part outdated so we want to have a "fresh start". You should expect a new list of items here soon. It doesn't mean that all the old items are out of question, or they aren't important, probably the opposite and you will see most of them again here soon.
|
||||
|
||||
## Recently completed
|
||||
|
||||
### MongoDB shared hosting on Cloud
|
||||
- Leaders: Meteor Software
|
||||
- Status: shipped in January 2021
|
||||
|
||||
You can host your app on Galaxy and use our shared MongoDB for non-commercial/non-production apps. We don't recommend a shared MongoDB instance for production apps.
|
||||
|
||||
### Free deploy on Cloud
|
||||
- Leaders: Meteor Software
|
||||
- Status: shipped in January 2021
|
||||
|
||||
Meteor free deploy is back.
|
||||
|
||||
### Hot Module Replacement
|
||||
- Leaders: [zodern](https://github.com/zodern)
|
||||
- Status: In Progress
|
||||
- Status: shipped in January 2021
|
||||
- PRs: https://github.com/meteor/meteor/pull/11117
|
||||
|
||||
HMR in Meteor, we already have a work in progress here, you can provide feedback already, check the PR.
|
||||
HMR is avaible since Meteor 2.0
|
||||
|
||||
### Transition as much as possible to NPM
|
||||
- Leaders: <you?>
|
||||
- Status: -
|
||||
- PRs:
|
||||
- PoC using base64 package as example [#10996](https://github.com/meteor/meteor/pull/10996)
|
||||
|
||||
Migrate packages that do not depend on Meteor exclusive features to NPM and we also continue to encourage new packages to be published as NPM packages when possible.
|
||||
|
||||
## Cordova
|
||||
### Cordova documentation
|
||||
- Leaders: [Filipe Névola](https://github.com/filipenevola)
|
||||
- Status: In Progress
|
||||
- PRs: https://github.com/meteor/meteor/pull/11072
|
||||
|
||||
Provide an example with mobile native configurations already in place such as `mobile-config.js`, sample assets, Fastlane scripts, etc. Also improve docs and guide ([Forums post](https://forums.meteor.com/t/lets-create-the-ultimate-cordova-hot-code-push-faq-doc/50500)).
|
||||
|
||||
## DB
|
||||
### Minimongo secondary index support
|
||||
- Leaders: [Brian Mulhall](https://github.com/BrianMulhall)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Improve index support for Minimongo to enable better performance in the client for databases with thousands of documents. ([Issue #10703](https://github.com/meteor/meteor/issues/10703))
|
||||
|
||||
## Documentation
|
||||
### Step-by-step guide
|
||||
- Leaders: <you?>
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Provide a nice and friendly introduction for people that are learning Meteor.
|
||||
|
||||
### Update Angular Tutorial
|
||||
- Leaders: [Brian Mulhall](https://github.com/BrianMulhall)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Angular tutorial should reflect latest best practices for using Meteor and Angular together.
|
||||
|
||||
React tutorial should reflect latest best practices for using Meteor and React together.
|
||||
|
||||
### PWA documentation
|
||||
- Leaders: [Filipe Névola](https://github.com/filipenevola)
|
||||
- Status: In Progress
|
||||
- PRs: -
|
||||
|
||||
Provide an example with PWA configurations already in place such as `manifest`, service worker, Open Graph meta tags, etc. Also improve docs and guide.
|
||||
|
||||
### SSR documentation
|
||||
- Leaders: [Kevin Newman](https://github.com/CaptainN) / [Eric Burel](https://github.com/eric-burel)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Provide a skeleton with SSR configurations already in place.
|
||||
|
||||
Relevant issues:
|
||||
- https://github.com/meteor/meteor-feature-requests/issues/174
|
||||
|
||||
### Tests documentation
|
||||
- Leaders: [Simon Schick](https://github.com/SimonSimCity) / [Florian Bienefelt](https://github.com/Floriferous)
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Provide samples on how to run tests in Meteor these samples should include unit tests and also cypress tests.
|
||||
|
||||
### Svelte
|
||||
- Leaders: [Brian Mulhall](https://github.com/BrianMulhall)
|
||||
- Status: In Progress
|
||||
- PRs: https://github.com/meteor/simple-todos-svelte
|
||||
|
||||
Tutorial is ready. We want a create command (--svelte) yet and more docs.
|
||||
|
||||
### Third-party tools with their own build steps
|
||||
|
||||
- Leaders: <you?>
|
||||
- Status: -
|
||||
- PRs: -
|
||||
|
||||
Remove limitations that prevent using third-party tools with their own build steps, such as Storybook or Jest.
|
||||
|
||||
Relevant discussions:
|
||||
- https://github.com/meteor/meteor/pull/10811#issuecomment-564726713
|
||||
- https://github.com/storybookjs/storybook/issues/5975
|
||||
|
||||
## Recently completed
|
||||
### Vue.js
|
||||
- Leaders: [Brian Mulhall](https://github.com/BrianMulhall)
|
||||
- Status: shipped in August 2020
|
||||
|
||||
17
examples/.gitignore
vendored
17
examples/.gitignore
vendored
@@ -1,17 +0,0 @@
|
||||
# Each individual example should include 'local' in foo/.meteor/.gitignore.
|
||||
# However, we also include this top-level .gitignore so that the following
|
||||
# situation:
|
||||
# $ git checkout some-branch-with-a-new-example
|
||||
# $ (cd examples/unfinished/new-example; meteor)
|
||||
# $ git checkout devel
|
||||
# doesn't leave you with tons of files in
|
||||
# examples/unfinished/new-example/.meteor/local showing up in your 'git status'.
|
||||
|
||||
*/.meteor/local
|
||||
*/*/.meteor/local
|
||||
|
||||
# We don't want to check example project id files into the main meteor
|
||||
# repo... but we do want users who create apps from the examples to check
|
||||
# *their* project id files into their repos, so we put this ignore line
|
||||
# here rather than in the examples/FOO/.meteor/.gitignore.
|
||||
*/.meteor/.id
|
||||
@@ -1 +0,0 @@
|
||||
0.6.0
|
||||
@@ -1,8 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
insecure
|
||||
preserve-inputs
|
||||
@@ -1 +0,0 @@
|
||||
0.7.0.1
|
||||
@@ -1,15 +0,0 @@
|
||||
<head>
|
||||
<title>Client Info</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> info}}
|
||||
</body>
|
||||
|
||||
<template name="info">
|
||||
<h1>Client Info</h1>
|
||||
|
||||
<p>Information about this client available on the server:</p>
|
||||
|
||||
<pre>{{info}}</pre>
|
||||
</template>
|
||||
@@ -1,19 +0,0 @@
|
||||
if (Meteor.isServer) {
|
||||
Meteor.publish("clientInfo", function () {
|
||||
var self = this;
|
||||
self.added("clientInfo", "info", {
|
||||
clientAddress: self.connection.clientAddress,
|
||||
httpHeaders: self.connection.httpHeaders
|
||||
});
|
||||
self.ready();
|
||||
});
|
||||
}
|
||||
|
||||
if (Meteor.isClient) {
|
||||
Meteor.subscribe("clientInfo");
|
||||
var ClientInfo = new Mongo.Collection("clientInfo");
|
||||
|
||||
Template.info.info = function () {
|
||||
return EJSON.stringify(ClientInfo.findOne("info"), {indent: true});
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
0.6.0
|
||||
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,6 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
@@ -1,13 +0,0 @@
|
||||
# Defer in Inactive Tab
|
||||
|
||||
Tests that `Meteor.defer` works in an inactive tab in iOS Safari.
|
||||
|
||||
(`setTimeout` and `setInterval` events aren't delivered to inactive
|
||||
tabs in iOS Safari until they become active again).
|
||||
|
||||
Sadly we have to run the test manually because scripts aren't allowed
|
||||
to open windows themselves except in response to user events.
|
||||
|
||||
This test will not run on Chrome for iOS because the storage event is
|
||||
not implemented in that browser. Also doesn't attempt to run on
|
||||
versions of IE that don't support `window.addEventListener`.
|
||||
@@ -1,52 +0,0 @@
|
||||
<head>
|
||||
<title>defer in inactive tab</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> route}}
|
||||
</body>
|
||||
|
||||
<template name="route">
|
||||
{{#if isParent}}
|
||||
{{> parent}}
|
||||
{{else}}
|
||||
{{> child}}
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
<template name="parent">
|
||||
<h1>Test Defer in Inactive Tab</h1>
|
||||
|
||||
<p>
|
||||
Step one: open second tab:
|
||||
<button id="openTab">Open Tab</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Step two: run test:
|
||||
<button id="runTest">Run Test</button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In a successful test the test status will immediately change to
|
||||
"test successful". (If you switch to the child tab yourself and
|
||||
that makes the test claim to be successful, that's actually an
|
||||
invalid test because you're letting the child tab become the
|
||||
active tab).
|
||||
</p>
|
||||
|
||||
<p style="padding: 1em; outline: 1px solid gray">
|
||||
Test status: <b>{{testStatus}}</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
After the test has run successfully you can close the child tab.
|
||||
</p>
|
||||
|
||||
</template>
|
||||
|
||||
<template name="child">
|
||||
<p>This is the child.</p>
|
||||
<p>Switch back to the first tab and run the test.</p>
|
||||
</template>
|
||||
@@ -1,57 +0,0 @@
|
||||
if (Meteor.isClient) {
|
||||
|
||||
var isParent = (window.location.pathname === '/');
|
||||
var isChild = ! isParent;
|
||||
|
||||
Template.route.isParent = function () {
|
||||
return isParent;
|
||||
};
|
||||
|
||||
Template.parent.testStatus = function () {
|
||||
return Session.get('testStatus');
|
||||
};
|
||||
|
||||
Template.parent.events({
|
||||
'click #openTab': function () {
|
||||
window.open('/child');
|
||||
},
|
||||
|
||||
'click #runTest': function () {
|
||||
if (localStorage.getItem('ping') === '!' ||
|
||||
localStorage.getItem('pong') === '!') {
|
||||
Session.set('testStatus', 'Test already run. Close the second tab (if open), refresh this page, and run again.');
|
||||
}
|
||||
else {
|
||||
localStorage.setItem('ping', '!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isParent) {
|
||||
Session.set('testStatus', '');
|
||||
|
||||
Meteor.startup(function () {
|
||||
localStorage.setItem('ping', null);
|
||||
localStorage.setItem('pong', null);
|
||||
});
|
||||
window.addEventListener('storage', function (event) {
|
||||
if (event.key === 'pong' && event.newValue === '!') {
|
||||
Session.set('testStatus', 'test successful');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isChild) {
|
||||
window.addEventListener('storage', function (event) {
|
||||
if (event.key === 'ping' && event.newValue === '!') {
|
||||
// If we used setTimeout here in iOS Safari it wouldn't
|
||||
// work (unless we switched tabs) because setTimeout and
|
||||
// setInterval events don't fire in inactive tabs.
|
||||
Meteor.defer(function () {
|
||||
localStorage.setItem('pong', '!');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,10 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
autopublish
|
||||
insecure
|
||||
preserve-inputs
|
||||
ui
|
||||
@@ -1 +0,0 @@
|
||||
none
|
||||
@@ -1,18 +0,0 @@
|
||||
/* CSS declarations go here */
|
||||
|
||||
|
||||
* { margin: 0; padding: 0 }
|
||||
|
||||
#grid td {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.color0 { background: #eee; }
|
||||
.color1 { background: #d8f; }
|
||||
.color2 { background: #8c3; }
|
||||
.color3 { background: #39d; }
|
||||
.color4 { background: #d96; }
|
||||
.color5 { background: #a95; }
|
||||
@@ -1,7 +0,0 @@
|
||||
<head>
|
||||
<title>domrange-grid</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
@@ -1,105 +0,0 @@
|
||||
if (Meteor.isClient) {
|
||||
Meteor.startup(function () {
|
||||
var N = 10;
|
||||
var numColors = 6;
|
||||
var colors = [];
|
||||
for(var z = 0; z < numColors; z++)
|
||||
colors[z] = z;
|
||||
|
||||
var guid = 1;
|
||||
|
||||
var table = $('<table id="grid"></table>');
|
||||
$(table).appendTo("body");
|
||||
var rows = [];
|
||||
var tableContent = new UI.DomRange;
|
||||
var makeCell = function (row) {
|
||||
var cells = row.cells;
|
||||
var tr = row.dom.elements()[0];
|
||||
var cell = {color: Random.choice(colors),
|
||||
guid: String(guid++)};
|
||||
cell.dom = new UI.DomRange(cell);
|
||||
cells.push(cell);
|
||||
cell.dom.add(cell.guid, $('<td class="color' +
|
||||
cell.color + '">' +
|
||||
cell.color + '</td>'));
|
||||
row.content.add(cell.guid, cell);
|
||||
};
|
||||
var makeRow = function () {
|
||||
var row = {cells: [], guid: String(guid++),
|
||||
content: new UI.DomRange};
|
||||
row.dom = new UI.DomRange(row);
|
||||
rows.push(row);
|
||||
tableContent.add(row.guid, row);
|
||||
var tr = $("<tr></tr>")[0];
|
||||
row.dom.add(tr);
|
||||
UI.DomRange.insert(row.content, tr);
|
||||
var cells = row.cells;
|
||||
for(var c = 0; c < N; c++)
|
||||
makeCell(row);
|
||||
};
|
||||
for (var r = 0; r < N; r++)
|
||||
makeRow();
|
||||
|
||||
UI.DomRange.insert(tableContent, table[0]);
|
||||
|
||||
$(document).on('keydown', function (evt) {
|
||||
var deltaN = 0;
|
||||
var deltaC = 0;
|
||||
if (evt.which === 38) {
|
||||
deltaN = 1; // up
|
||||
} else if (evt.which === 40) {
|
||||
deltaN = -1; // down
|
||||
} else if (evt.which === 37) {
|
||||
deltaC = -1; // left
|
||||
} else if (evt.which === 39) {
|
||||
deltaC = 1; // right
|
||||
} else if (evt.which === 32) {
|
||||
// spacebar
|
||||
var row0 = rows.shift();
|
||||
rows.push(row0);
|
||||
tableContent.moveBefore(row0.guid, null);
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var cell0 = row.cells.shift();
|
||||
row.cells.push(cell0);
|
||||
row.content.moveBefore(cell0.guid, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (deltaN === 1) {
|
||||
N += 1;
|
||||
for (var i = 0; i < N - 1; i++)
|
||||
// lengthen old rows
|
||||
makeCell(rows[i]);
|
||||
makeRow();
|
||||
} else if (deltaN === -1) {
|
||||
if (N === 0)
|
||||
return;
|
||||
N -= 1;
|
||||
tableContent.remove(rows[N].guid);
|
||||
rows.length = N;
|
||||
for (var i = 0; i < N; i++) {
|
||||
var row = rows[i];
|
||||
row.content.remove(row.cells[N].guid);
|
||||
rows[i].cells.length = N;
|
||||
}
|
||||
}
|
||||
|
||||
if (deltaC) {
|
||||
for (var r = 0; r < N; r++) {
|
||||
var row = rows[r];
|
||||
for (var c = 0; c < N; c++) {
|
||||
var cell = row.cells[c];
|
||||
var td = cell.dom.elements()[0];
|
||||
var color =
|
||||
(cell.color =
|
||||
(cell.color + deltaC + numColors)
|
||||
% numColors);
|
||||
td.innerHTML = color;
|
||||
td.className = 'color' + color;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
1
examples/other/login-demo/.meteor/.gitignore
vendored
1
examples/other/login-demo/.meteor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,8 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
preserve-inputs
|
||||
accounts-google
|
||||
standard-app-packages
|
||||
@@ -1 +0,0 @@
|
||||
none
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
* { padding: 0; margin: 0; }
|
||||
|
||||
#main {
|
||||
margin: 50px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.msgDiv {
|
||||
margin: 30px;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 5px;
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
#readme {
|
||||
margin: 20px;
|
||||
border: 1px solid #ccc;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 16px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<head>
|
||||
<title>login-demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
{{> main}}
|
||||
</div>
|
||||
<div id="readme">
|
||||
<p>This is a minimal app where you need to log in to see the database. There's also a loading screen while logging in and until the initial data is loaded.</p>
|
||||
<p>There are three top-level screens corresponding to the three possible states of the app:</p>
|
||||
<ul>
|
||||
<li>Logging in / Loading — when <code>{{loggingIn}}</code> is true</li>
|
||||
<li>Logged in — when there is a <code>{{currentUser}}</code></li>
|
||||
<li>Logged out — otherwise</li>
|
||||
</ul>
|
||||
<p>If you reload the page while logged in, you'll start in the "logging in" state and see the "Loading..." message until the data loads. Because logging in doesn't complete until all subscriptions have been rerun and finished loading, and the app only serves data when you're logged in, the "logging in" state encompasses loading the initial data for all subscriptions and is the only loading screen we need.</p>
|
||||
<p>To configure this app for Google auth, the easiest way is to add the <code>accounts-ui</code> package, add <code>{{> loginButtons}}</code> to the end of the body, and use the configuration wizard.</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<template name="main">
|
||||
{{#if loggingIn}}
|
||||
<div class="loading">Loading...</div>
|
||||
{{else}}
|
||||
{{#if currentUser}}
|
||||
<div class="msgDiv">
|
||||
Signed in as: {{currentUser.services.google.email}}
|
||||
</div>
|
||||
<a href="#" id="logout">Sign out</a>
|
||||
{{else}}
|
||||
<a href="#" id="login">Sign In With Google</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div class="msgDiv">
|
||||
Client can see {{numGizmos}} gizmos.
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,57 +0,0 @@
|
||||
Gizmos = new Mongo.Collection("gizmos");
|
||||
|
||||
if (Meteor.isClient) {
|
||||
|
||||
var allGizmos = Meteor.subscribe("allGizmos");
|
||||
|
||||
Template.main.numGizmos = function () {
|
||||
return Gizmos.find().count();
|
||||
};
|
||||
|
||||
Template.main.events({
|
||||
'click #login': function (evt) {
|
||||
Meteor.loginWithGoogle(function (err) {
|
||||
if (err)
|
||||
Meteor._debug(err);
|
||||
});
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click #logout': function (evt) {
|
||||
Meteor.logout(function (err) {
|
||||
if (err)
|
||||
Meteor._debug(err);
|
||||
});
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Meteor.isServer) {
|
||||
|
||||
Meteor.startup(function () {
|
||||
// populate the Gizmos collection if it's empty on startup
|
||||
if (Gizmos.find().count() === 0) {
|
||||
for (var i = 0; i < 1000; i++)
|
||||
Gizmos.insert({ name: "Gizmo " + i });
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.publish("allGizmos", function () {
|
||||
// Only publish the Gizmos if user is logged in.
|
||||
var user = this.userId && Meteor.users.findOne(this.userId);
|
||||
if (user) {
|
||||
// potentially put other conditions on user here...
|
||||
return Gizmos.find({});
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
Meteor.publish(null, function () {
|
||||
// If logged in, autopublish the current user's Google email
|
||||
// to the client (which isn't published by default).
|
||||
return this.userId &&
|
||||
Meteor.users.find(this.userId,
|
||||
{fields: {'services.google.email': 1}});
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
# This file contains information which helps Meteor properly upgrade your
|
||||
# app when you run 'meteor update'. You should check it into version control
|
||||
# with your project.
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
1
examples/other/parties/.meteor/.gitignore
vendored
1
examples/other/parties/.meteor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,14 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
accounts-ui
|
||||
accounts-password
|
||||
d3
|
||||
bootstrap
|
||||
email
|
||||
accounts-facebook
|
||||
accounts-twitter
|
||||
audit-argument-checks
|
||||
@@ -1 +0,0 @@
|
||||
METEOR@0.9.4
|
||||
@@ -1,72 +0,0 @@
|
||||
accounts-base@1.1.2
|
||||
accounts-facebook@1.0.2
|
||||
accounts-oauth@1.1.2
|
||||
accounts-password@1.0.3
|
||||
accounts-twitter@1.0.2
|
||||
accounts-ui-unstyled@1.1.3
|
||||
accounts-ui@1.1.2
|
||||
application-configuration@1.0.3
|
||||
audit-argument-checks@1.0.1
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
bootstrap@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
d3@1.0.0
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
email@1.0.4
|
||||
facebook@1.1.1
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
less@1.0.10
|
||||
livedata@1.0.11
|
||||
localstorage@1.0.1
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
npm-bcrypt@0.7.7
|
||||
oauth1@1.1.1
|
||||
oauth2@1.1.1
|
||||
oauth@1.1.1
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
service-configuration@1.0.2
|
||||
session@1.0.3
|
||||
sha@1.0.1
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
srp@1.0.1
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
twitter@1.1.1
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
@@ -1,285 +0,0 @@
|
||||
// All Tomorrow's Parties -- client
|
||||
|
||||
Meteor.subscribe("directory");
|
||||
Meteor.subscribe("parties");
|
||||
|
||||
// If no party selected, or if the selected party was deleted, select one.
|
||||
Meteor.startup(function () {
|
||||
Tracker.autorun(function () {
|
||||
var selected = Session.get("selected");
|
||||
if (! selected || ! Parties.findOne(selected)) {
|
||||
var party = Parties.findOne();
|
||||
if (party)
|
||||
Session.set("selected", party._id);
|
||||
else
|
||||
Session.set("selected", null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Party details sidebar
|
||||
|
||||
Template.details.helpers({
|
||||
party: function () {
|
||||
return Parties.findOne(Session.get("selected"));
|
||||
},
|
||||
anyParties: function () {
|
||||
return Parties.find().count() > 0;
|
||||
},
|
||||
creatorName: function () {
|
||||
var owner = Meteor.users.findOne(this.owner);
|
||||
if (owner._id === Meteor.userId())
|
||||
return "me";
|
||||
return displayName(owner);
|
||||
},
|
||||
canRemove: function () {
|
||||
return this.owner === Meteor.userId() && attending(this) === 0;
|
||||
},
|
||||
maybeChosen: function (what) {
|
||||
var myRsvp = _.find(this.rsvps, function (r) {
|
||||
return r.user === Meteor.userId();
|
||||
}) || {};
|
||||
|
||||
return what == myRsvp.rsvp ? "chosen btn-inverse" : "";
|
||||
}
|
||||
});
|
||||
|
||||
Template.details.events({
|
||||
'click .rsvp_yes': function () {
|
||||
Meteor.call("rsvp", Session.get("selected"), "yes");
|
||||
return false;
|
||||
},
|
||||
'click .rsvp_maybe': function () {
|
||||
Meteor.call("rsvp", Session.get("selected"), "maybe");
|
||||
return false;
|
||||
},
|
||||
'click .rsvp_no': function () {
|
||||
Meteor.call("rsvp", Session.get("selected"), "no");
|
||||
return false;
|
||||
},
|
||||
'click .invite': function () {
|
||||
openInviteDialog();
|
||||
return false;
|
||||
},
|
||||
'click .remove': function () {
|
||||
Parties.remove(this._id);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Party attendance widget
|
||||
|
||||
Template.attendance.helpers({
|
||||
rsvpName: function () {
|
||||
var user = Meteor.users.findOne(this.user);
|
||||
return displayName(user);
|
||||
},
|
||||
|
||||
outstandingInvitations: function () {
|
||||
var party = Parties.findOne(this._id);
|
||||
return Meteor.users.find({$and: [
|
||||
{_id: {$in: party.invited}}, // they're invited
|
||||
{_id: {$nin: _.pluck(party.rsvps, 'user')}} // but haven't RSVP'd
|
||||
]});
|
||||
},
|
||||
|
||||
invitationName: function () {
|
||||
return displayName(this);
|
||||
},
|
||||
|
||||
rsvpIs: function (what) {
|
||||
return this.rsvp === what;
|
||||
},
|
||||
|
||||
nobody: function () {
|
||||
return ! this.public && (this.rsvps.length + this.invited.length === 0);
|
||||
},
|
||||
|
||||
canInvite: function () {
|
||||
return ! this.public && this.owner === Meteor.userId();
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Map display
|
||||
|
||||
// Use jquery to get the position clicked relative to the map element.
|
||||
var coordsRelativeToElement = function (element, event) {
|
||||
var offset = $(element).offset();
|
||||
var x = event.pageX - offset.left;
|
||||
var y = event.pageY - offset.top;
|
||||
return { x: x, y: y };
|
||||
};
|
||||
|
||||
Template.map.events({
|
||||
'mousedown circle, mousedown text': function (event, template) {
|
||||
Session.set("selected", event.currentTarget.id);
|
||||
},
|
||||
'dblclick .map': function (event, template) {
|
||||
if (! Meteor.userId()) // must be logged in to create events
|
||||
return;
|
||||
var coords = coordsRelativeToElement(event.currentTarget, event);
|
||||
openCreateDialog(coords.x / 500, coords.y / 500);
|
||||
}
|
||||
});
|
||||
|
||||
Template.map.onRendered(function () {
|
||||
var self = this;
|
||||
self.node = self.find("svg");
|
||||
|
||||
if (! self.handle) {
|
||||
self.handle = Tracker.autorun(function () {
|
||||
var selected = Session.get('selected');
|
||||
var selectedParty = selected && Parties.findOne(selected);
|
||||
var radius = function (party) {
|
||||
return 10 + Math.sqrt(attending(party)) * 10;
|
||||
};
|
||||
|
||||
// Draw a circle for each party
|
||||
var updateCircles = function (group) {
|
||||
group.attr("id", function (party) { return party._id; })
|
||||
.attr("cx", function (party) { return party.x * 500; })
|
||||
.attr("cy", function (party) { return party.y * 500; })
|
||||
.attr("r", radius)
|
||||
.attr("class", function (party) {
|
||||
return party.public ? "public" : "private";
|
||||
})
|
||||
.style('opacity', function (party) {
|
||||
return selected === party._id ? 1 : 0.6;
|
||||
});
|
||||
};
|
||||
|
||||
var circles = d3.select(self.node).select(".circles").selectAll("circle")
|
||||
.data(Parties.find().fetch(), function (party) { return party._id; });
|
||||
|
||||
updateCircles(circles.enter().append("circle"));
|
||||
updateCircles(circles.transition().duration(250).ease("cubic-out"));
|
||||
circles.exit().transition().duration(250).attr("r", 0).remove();
|
||||
|
||||
// Label each with the current attendance count
|
||||
var updateLabels = function (group) {
|
||||
group.attr("id", function (party) { return party._id; })
|
||||
.text(function (party) {return attending(party) || '';})
|
||||
.attr("x", function (party) { return party.x * 500; })
|
||||
.attr("y", function (party) { return party.y * 500 + radius(party)/2 })
|
||||
.style('font-size', function (party) {
|
||||
return radius(party) * 1.25 + "px";
|
||||
});
|
||||
};
|
||||
|
||||
var labels = d3.select(self.node).select(".labels").selectAll("text")
|
||||
.data(Parties.find().fetch(), function (party) { return party._id; });
|
||||
|
||||
updateLabels(labels.enter().append("text"));
|
||||
updateLabels(labels.transition().duration(250).ease("cubic-out"));
|
||||
labels.exit().remove();
|
||||
|
||||
// Draw a dashed circle around the currently selected party, if any
|
||||
var callout = d3.select(self.node).select("circle.callout")
|
||||
.transition().duration(250).ease("cubic-out");
|
||||
if (selectedParty)
|
||||
callout.attr("cx", selectedParty.x * 500)
|
||||
.attr("cy", selectedParty.y * 500)
|
||||
.attr("r", radius(selectedParty) + 10)
|
||||
.attr("class", "callout")
|
||||
.attr("display", '');
|
||||
else
|
||||
callout.attr("display", 'none');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Template.map.onDestroyed = function () {
|
||||
this.handle && this.handle.stop();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Create Party dialog
|
||||
|
||||
var openCreateDialog = function (x, y) {
|
||||
Session.set("createCoords", {x: x, y: y});
|
||||
Session.set("createError", null);
|
||||
Session.set("showCreateDialog", true);
|
||||
};
|
||||
|
||||
Template.page.helpers({
|
||||
showCreateDialog: function () {
|
||||
return Session.get("showCreateDialog");
|
||||
}
|
||||
});
|
||||
|
||||
Template.createDialog.events({
|
||||
'click .save': function (event, template) {
|
||||
var title = template.find(".title").value;
|
||||
var description = template.find(".description").value;
|
||||
var public = ! template.find(".private").checked;
|
||||
var coords = Session.get("createCoords");
|
||||
|
||||
if (title.length && description.length) {
|
||||
var id = createParty({
|
||||
title: title,
|
||||
description: description,
|
||||
x: coords.x,
|
||||
y: coords.y,
|
||||
public: public
|
||||
});
|
||||
|
||||
Session.set("selected", id);
|
||||
if (! public && Meteor.users.find().count() > 1)
|
||||
openInviteDialog();
|
||||
Session.set("showCreateDialog", false);
|
||||
} else {
|
||||
Session.set("createError",
|
||||
"It needs a title and a description, or why bother?");
|
||||
}
|
||||
},
|
||||
|
||||
'click .cancel': function () {
|
||||
Session.set("showCreateDialog", false);
|
||||
}
|
||||
});
|
||||
|
||||
Template.createDialog.helpers({
|
||||
error: function () {
|
||||
return Session.get("createError");
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Invite dialog
|
||||
|
||||
var openInviteDialog = function () {
|
||||
Session.set("showInviteDialog", true);
|
||||
};
|
||||
|
||||
Template.page.helpers({
|
||||
showInviteDialog: function () {
|
||||
return Session.get("showInviteDialog");
|
||||
}
|
||||
});
|
||||
|
||||
Template.inviteDialog.events({
|
||||
'click .invite': function (event, template) {
|
||||
Meteor.call('invite', Session.get("selected"), this._id);
|
||||
},
|
||||
'click .done': function (event, template) {
|
||||
Session.set("showInviteDialog", false);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Template.inviteDialog.helpers({
|
||||
uninvited: function () {
|
||||
var party = Parties.findOne(Session.get("selected"));
|
||||
if (! party)
|
||||
return []; // party hasn't loaded yet
|
||||
return Meteor.users.find({$nor: [{_id: {$in: party.invited}},
|
||||
{_id: party.owner}]});
|
||||
},
|
||||
|
||||
displayName: function () {
|
||||
return displayName(this);
|
||||
}
|
||||
});
|
||||
@@ -1,81 +0,0 @@
|
||||
.header {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-top: -18px;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background-color: #000000;
|
||||
opacity: .4;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.invite-row .invite {
|
||||
margin: 10px 10px 10px 0;
|
||||
}
|
||||
|
||||
.rsvp-buttons {
|
||||
text-align: center;
|
||||
margin: 40px 0 40px 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin: 20px 0 20px 0;
|
||||
}
|
||||
|
||||
.attendance .who {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.attendance .invite {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input.chosen {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.map {
|
||||
position: relative;
|
||||
background-image: url('/soma.png');
|
||||
background-position: -20px -20px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.map circle.public {
|
||||
fill: #49AFCD;
|
||||
}
|
||||
|
||||
.map circle.private {
|
||||
fill: #DA4F49;
|
||||
}
|
||||
|
||||
.map text {
|
||||
text-anchor: middle;
|
||||
fill: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.map circle.callout {
|
||||
stroke-width: 5px;
|
||||
stroke-dasharray: 9, 5;
|
||||
stroke-opacity: .8;
|
||||
fill: none;
|
||||
stroke: red;
|
||||
}
|
||||
|
||||
.attribution {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background-color: white;
|
||||
padding: 3px;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
<head>
|
||||
<title>All Tomorrow's Parties</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> page}}
|
||||
</body>
|
||||
|
||||
<template name="page">
|
||||
{{#if showCreateDialog}}
|
||||
{{> createDialog}}
|
||||
{{/if}}
|
||||
|
||||
{{#if showInviteDialog}}
|
||||
{{> inviteDialog}}
|
||||
{{/if}}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span1"> </div>
|
||||
|
||||
<div class="span10">
|
||||
<div class="header row">
|
||||
<div class="span5">
|
||||
<h3 style="margin-bottom: 0px">All Tomorrow's Parties</h3>
|
||||
</div>
|
||||
<div class="span5">
|
||||
<div style="float: right">
|
||||
{{> loginButtons align="right"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="span6">
|
||||
{{> map}}
|
||||
{{#if currentUser}}
|
||||
<div class="pagination-centered">
|
||||
<em><small>Double click the map to post a party!</small></em>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="span4">
|
||||
{{> details}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="span1"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="map">
|
||||
<div class="map">
|
||||
<svg width="500" height="500">
|
||||
<circle class="callout" cx=-100 cy=-100></circle>
|
||||
<g class="circles"></g>
|
||||
<g class="labels"></g>
|
||||
</svg>
|
||||
<div>
|
||||
<small class="attribution muted">©
|
||||
<a href="http://www.openstreetmap.org/?lat=37.78212&lon=-122.40146&zoom=15&layers=M"
|
||||
target="_blank">OpenStreetMap</a> contributors</small>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="details">
|
||||
<div class="details">
|
||||
{{#if party}}
|
||||
{{#with party}}
|
||||
<h1>{{title}}</h1>
|
||||
|
||||
<div class="description">{{description}}</div>
|
||||
|
||||
{{> attendance}}
|
||||
|
||||
<div class="rsvp-buttons">
|
||||
{{#if currentUser}}
|
||||
<input type="button" value="I'm going!"
|
||||
class="btn btn-small rsvp_yes {{maybeChosen "yes"}}">
|
||||
<input type="button" value="Maybe"
|
||||
class="btn btn-small rsvp_maybe {{maybeChosen "maybe"}}">
|
||||
<input type="button" value="No"
|
||||
class="btn btn-small rsvp_no {{maybeChosen "no"}}">
|
||||
{{else}}
|
||||
<i>Sign in to RSVP for this party.</i>
|
||||
{{/if}}
|
||||
<p><small>Posted by {{creatorName}}</small></p>
|
||||
</div>
|
||||
|
||||
{{#if canRemove}}
|
||||
<div class="alert alert-info"><small>
|
||||
You posted this party and nobody is signed up to go, so if
|
||||
you like, you could
|
||||
<b><a href="#" class="remove">delete this listing</a></b>.
|
||||
</small></div>
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
{{else}}
|
||||
<h1 class="muted pagination-centered">
|
||||
{{#if anyParties}}
|
||||
Click a party to select it
|
||||
{{else}}
|
||||
Sign in and double click the map to post a party
|
||||
{{/if}}
|
||||
</h1>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="attendance">
|
||||
<div class="attendance well well-small">
|
||||
<div class="muted who"><b>Who</b></div>
|
||||
{{#if public}}
|
||||
<div>
|
||||
<b>Everyone</b>
|
||||
<span class="label label-inverse pull-right">Invited</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#each rsvps}}
|
||||
<div>
|
||||
{{rsvpName}}
|
||||
{{#if rsvpIs "yes"}}
|
||||
<span class="label label-success pull-right">Going</span>
|
||||
{{/if}}
|
||||
{{#if rsvpIs "maybe"}}
|
||||
<span class="label label-info pull-right">Maybe</span>
|
||||
{{/if}}
|
||||
{{#if rsvpIs "no"}}
|
||||
<span class="label label pull-right">No</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
{{#unless public}}
|
||||
{{#each outstandingInvitations}}
|
||||
<div>
|
||||
{{invitationName}}
|
||||
<span class="label label-inverse pull-right">Invited</span>
|
||||
</div>
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
|
||||
{{#if nobody}}
|
||||
<div>Nobody.</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if canInvite}}
|
||||
<div class="invite">
|
||||
<a href="#" class="btn btn-mini invite">Invite people</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="createDialog">
|
||||
<div class="mask"> </div>
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close cancel">×</button>
|
||||
<h3>Add party</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
{{#if error}}
|
||||
<div class="alert alert-error">{{error}}</div>
|
||||
{{/if}}
|
||||
|
||||
<label>Title</label>
|
||||
<input type="text" class="title span5">
|
||||
|
||||
<label>Description</label>
|
||||
<textarea class="description span5"></textarea>
|
||||
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" class="private">
|
||||
Private party — invitees only
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn cancel">Cancel</a>
|
||||
<a href="#" class="btn btn-primary save">Add party</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="inviteDialog">
|
||||
<div class="mask"> </div>
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close done">×</button>
|
||||
<h3>Invite people</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
{{#each uninvited}}
|
||||
<div class="invite-row">
|
||||
<a href="#" class="btn invite">Invite</a>
|
||||
{{displayName}}
|
||||
</div>
|
||||
{{else}}
|
||||
Everyone on the site has already been invited.
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-primary done">Done</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
// All Tomorrow's Parties -- data model
|
||||
// Loaded on both the client and the server
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Parties
|
||||
|
||||
/*
|
||||
Each party is represented by a document in the Parties collection:
|
||||
owner: user id
|
||||
x, y: Number (screen coordinates in the interval [0, 1])
|
||||
title, description: String
|
||||
public: Boolean
|
||||
invited: Array of user id's that are invited (only if !public)
|
||||
rsvps: Array of objects like {user: userId, rsvp: "yes"} (or "no"/"maybe")
|
||||
*/
|
||||
Parties = new Mongo.Collection("parties");
|
||||
|
||||
Parties.allow({
|
||||
insert: function (userId, party) {
|
||||
return false; // no cowboy inserts -- use createParty method
|
||||
},
|
||||
update: function (userId, party, fields, modifier) {
|
||||
if (userId !== party.owner)
|
||||
return false; // not the owner
|
||||
|
||||
var allowed = ["title", "description", "x", "y"];
|
||||
if (_.difference(fields, allowed).length)
|
||||
return false; // tried to write to forbidden field
|
||||
|
||||
// A good improvement would be to validate the type of the new
|
||||
// value of the field (and if a string, the length.) In the
|
||||
// future Meteor will have a schema system to makes that easier.
|
||||
return true;
|
||||
},
|
||||
remove: function (userId, party) {
|
||||
// You can only remove parties that you created and nobody is going to.
|
||||
return party.owner === userId && attending(party) === 0;
|
||||
}
|
||||
});
|
||||
|
||||
attending = function (party) {
|
||||
return (_.groupBy(party.rsvps, 'rsvp').yes || []).length;
|
||||
};
|
||||
|
||||
var NonEmptyString = Match.Where(function (x) {
|
||||
check(x, String);
|
||||
return x.length !== 0;
|
||||
});
|
||||
|
||||
var Coordinate = Match.Where(function (x) {
|
||||
check(x, Number);
|
||||
return x >= 0 && x <= 1;
|
||||
});
|
||||
|
||||
createParty = function (options) {
|
||||
var id = Random.id();
|
||||
Meteor.call('createParty', _.extend({ _id: id }, options));
|
||||
return id;
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
// options should include: title, description, x, y, public
|
||||
createParty: function (options) {
|
||||
check(options, {
|
||||
title: NonEmptyString,
|
||||
description: NonEmptyString,
|
||||
x: Coordinate,
|
||||
y: Coordinate,
|
||||
public: Match.Optional(Boolean),
|
||||
_id: Match.Optional(NonEmptyString)
|
||||
});
|
||||
|
||||
if (options.title.length > 100)
|
||||
throw new Meteor.Error(413, "Title too long");
|
||||
if (options.description.length > 1000)
|
||||
throw new Meteor.Error(413, "Description too long");
|
||||
if (! this.userId)
|
||||
throw new Meteor.Error(403, "You must be logged in");
|
||||
|
||||
var id = options._id || Random.id();
|
||||
Parties.insert({
|
||||
_id: id,
|
||||
owner: this.userId,
|
||||
x: options.x,
|
||||
y: options.y,
|
||||
title: options.title,
|
||||
description: options.description,
|
||||
public: !! options.public,
|
||||
invited: [],
|
||||
rsvps: []
|
||||
});
|
||||
return id;
|
||||
},
|
||||
|
||||
invite: function (partyId, userId) {
|
||||
check(partyId, String);
|
||||
check(userId, String);
|
||||
var party = Parties.findOne(partyId);
|
||||
if (! party || party.owner !== this.userId)
|
||||
throw new Meteor.Error(404, "No such party");
|
||||
if (party.public)
|
||||
throw new Meteor.Error(400,
|
||||
"That party is public. No need to invite people.");
|
||||
if (userId !== party.owner && ! _.contains(party.invited, userId)) {
|
||||
Parties.update(partyId, { $addToSet: { invited: userId } });
|
||||
|
||||
var from = contactEmail(Meteor.users.findOne(this.userId));
|
||||
var to = contactEmail(Meteor.users.findOne(userId));
|
||||
if (Meteor.isServer && to) {
|
||||
// This code only runs on the server. If you didn't want clients
|
||||
// to be able to see it, you could move it to a separate file.
|
||||
Email.send({
|
||||
from: "noreply@example.com",
|
||||
to: to,
|
||||
replyTo: from || undefined,
|
||||
subject: "PARTY: " + party.title,
|
||||
text:
|
||||
"Hey, I just invited you to '" + party.title + "' on All Tomorrow's Parties." +
|
||||
"\n\nCome check it out: " + Meteor.absoluteUrl() + "\n"
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
rsvp: function (partyId, rsvp) {
|
||||
check(partyId, String);
|
||||
check(rsvp, String);
|
||||
if (! this.userId)
|
||||
throw new Meteor.Error(403, "You must be logged in to RSVP");
|
||||
if (! _.contains(['yes', 'no', 'maybe'], rsvp))
|
||||
throw new Meteor.Error(400, "Invalid RSVP");
|
||||
var party = Parties.findOne(partyId);
|
||||
if (! party)
|
||||
throw new Meteor.Error(404, "No such party");
|
||||
if (! party.public && party.owner !== this.userId &&
|
||||
!_.contains(party.invited, this.userId))
|
||||
// private, but let's not tell this to the user
|
||||
throw new Meteor.Error(403, "No such party");
|
||||
|
||||
var rsvpIndex = _.indexOf(_.pluck(party.rsvps, 'user'), this.userId);
|
||||
if (rsvpIndex !== -1) {
|
||||
// update existing rsvp entry
|
||||
|
||||
if (Meteor.isServer) {
|
||||
// update the appropriate rsvp entry with $
|
||||
Parties.update(
|
||||
{_id: partyId, "rsvps.user": this.userId},
|
||||
{$set: {"rsvps.$.rsvp": rsvp}});
|
||||
} else {
|
||||
// minimongo doesn't yet support $ in modifier. as a temporary
|
||||
// workaround, make a modifier that uses an index. this is
|
||||
// safe on the client since there's only one thread.
|
||||
var modifier = {$set: {}};
|
||||
modifier.$set["rsvps." + rsvpIndex + ".rsvp"] = rsvp;
|
||||
Parties.update(partyId, modifier);
|
||||
}
|
||||
|
||||
// Possible improvement: send email to the other people that are
|
||||
// coming to the party.
|
||||
} else {
|
||||
// add new rsvp entry
|
||||
Parties.update(partyId,
|
||||
{$push: {rsvps: {user: this.userId, rsvp: rsvp}}});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Users
|
||||
|
||||
displayName = function (user) {
|
||||
if (user.profile && user.profile.name)
|
||||
return user.profile.name;
|
||||
return user.emails[0].address;
|
||||
};
|
||||
|
||||
var contactEmail = function (user) {
|
||||
if (user.emails && user.emails.length)
|
||||
return user.emails[0].address;
|
||||
if (user.services && user.services.facebook && user.services.facebook.email)
|
||||
return user.services.facebook.email;
|
||||
return null;
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 126 KiB |
@@ -1,10 +0,0 @@
|
||||
// All Tomorrow's Parties -- server
|
||||
|
||||
Meteor.publish("directory", function () {
|
||||
return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});
|
||||
});
|
||||
|
||||
Meteor.publish("parties", function () {
|
||||
return Parties.find(
|
||||
{$or: [{"public": true}, {invited: this.userId}, {owner: this.userId}]});
|
||||
});
|
||||
1
examples/other/quiescence/.meteor/.gitignore
vendored
1
examples/other/quiescence/.meteor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,9 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
insecure
|
||||
preserve-inputs
|
||||
random
|
||||
standard-app-packages
|
||||
@@ -1 +0,0 @@
|
||||
0.6.0
|
||||
@@ -1,35 +0,0 @@
|
||||
<head>
|
||||
<title>quiescence</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> clock}}
|
||||
{{> updated}}
|
||||
{{> stream}}
|
||||
</body>
|
||||
|
||||
<template name="clock">
|
||||
<h1>Current time</h1>
|
||||
<p>{{time}}</p>
|
||||
</template>
|
||||
|
||||
<template name="updated">
|
||||
<h1>Update object</h1>
|
||||
<p>The magic number is {{magic}}. Click the button to set it to a random
|
||||
integer in the client stub. The server will add 0.5 the that integer.</p>
|
||||
<button id='update-button'>Update</button>
|
||||
</template>
|
||||
|
||||
<template name="stream">
|
||||
<h1>Stream in results</h1>
|
||||
<p>Click the button. Note that the results stream in instead of appearing all
|
||||
at once. Note that the clock continues to tick while the streaming method
|
||||
is running. Note that the "update" button above works while the streaming
|
||||
method is running (ie, the server's "add 0.5" is processed).</p>
|
||||
<button id='stream-button'>Stream</button>
|
||||
<ul>
|
||||
{{#each results}}
|
||||
<li>{{text}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</template>
|
||||
@@ -1,96 +0,0 @@
|
||||
Time = new Mongo.Collection("time");
|
||||
Results = new Mongo.Collection("results");
|
||||
Magic = new Mongo.Collection("magic");
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Meteor.publish("time", function () {
|
||||
var self = this;
|
||||
var publishTime = function () {
|
||||
var when = + new Date;
|
||||
self.changed("time", "now", {timestamp: when});
|
||||
};
|
||||
self.added("time", "now", {});
|
||||
publishTime();
|
||||
self.ready();
|
||||
var interval = Meteor.setInterval(publishTime, 1000);
|
||||
self.onStop(function () {
|
||||
Meteor.clearInterval(interval);
|
||||
});
|
||||
});
|
||||
Meteor.publish("results", function () {
|
||||
return Results.find();
|
||||
});
|
||||
Meteor.publish("magic", function () {
|
||||
return Magic.find();
|
||||
});
|
||||
|
||||
Meteor.startup(function () {
|
||||
if (Magic.find().count() === 0) {
|
||||
Magic.insert({number: 42});
|
||||
}
|
||||
});
|
||||
|
||||
var Fiber = Npm.require('fibers');
|
||||
|
||||
var sleep = function (ms) {
|
||||
var fiber = Fiber.current;
|
||||
setTimeout(function() {
|
||||
fiber.run();
|
||||
}, ms);
|
||||
Fiber.yield();
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
getResults: function () {
|
||||
this.unblock();
|
||||
Results.remove({});
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
sleep(1000);
|
||||
Results.insert({i: i, text: 'result ' + i});
|
||||
}
|
||||
}});
|
||||
} else {
|
||||
Meteor.subscribe("time");
|
||||
Meteor.subscribe("results");
|
||||
Meteor.subscribe("magic");
|
||||
|
||||
Template.clock.time = function () {
|
||||
var now = Time.findOne('now');
|
||||
if (!now)
|
||||
return "(loading)";
|
||||
return new Date(now.timestamp).toTimeString();
|
||||
};
|
||||
|
||||
Template.updated.magic = function () {
|
||||
var singleton = Magic.findOne();
|
||||
if (!singleton)
|
||||
return "(loading)";
|
||||
return singleton.number;
|
||||
};
|
||||
Template.updated.events({
|
||||
'click #update-button': function () {
|
||||
var num = Math.round(Random.fraction()*100);
|
||||
Meteor.call('setMagic', num);
|
||||
}
|
||||
});
|
||||
|
||||
Template.stream.events({
|
||||
'click #stream-button': function () {
|
||||
Meteor.call('getResults');
|
||||
}
|
||||
});
|
||||
|
||||
Template.stream.results = function () {
|
||||
return Results.find({}, {sort: ['i']});
|
||||
};
|
||||
}
|
||||
|
||||
Meteor.methods({
|
||||
setMagic: function (num) {
|
||||
if (this.isSimulation) {
|
||||
Magic.update({}, {$set: {number: num}});
|
||||
} else {
|
||||
Magic.update({}, {$set: {number: num + 0.5}});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,7 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
autopublish
|
||||
standard-app-packages
|
||||
@@ -1 +0,0 @@
|
||||
0.6.0
|
||||
7034
examples/other/template-demo/client/d3.v2.js
vendored
7034
examples/other/template-demo/client/d3.v2.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
||||
body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, san-serif;
|
||||
width: 600px;
|
||||
margin: auto;
|
||||
padding: 25px 50px;
|
||||
border: 5px dashed #ccc;
|
||||
border-style: none dashed;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 50px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.clearboth {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes spinForward {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(360deg);}
|
||||
}
|
||||
|
||||
@-webkit-keyframes spinBackward {
|
||||
from {-webkit-transform: rotate(360deg);}
|
||||
to {-webkit-transform: rotate(0deg);}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 100px;
|
||||
border: 2px solid black;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.circles {
|
||||
float: left;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.circles svg {
|
||||
border: 2px solid #333;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<head>
|
||||
<title>Advanced Template Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> page}}
|
||||
</body>
|
||||
|
||||
<template name="page">
|
||||
<h1>Advanced Template Demo</h1>
|
||||
<p>
|
||||
This demo shows off the advanced features of Meteor's optional
|
||||
Spark-based templating system, including constant regions, node
|
||||
preservation, per-template state, and template lifecycle
|
||||
callbacks.
|
||||
</p>
|
||||
|
||||
{{> preserveDemo }}
|
||||
{{> constantDemo }}
|
||||
{{> stateDemo }}
|
||||
{{> d3Demo }}
|
||||
</template>
|
||||
|
||||
<template name="preserveDemo">
|
||||
<h2>Element preservation</h2>
|
||||
|
||||
<input type="button" value="X++" class="x">
|
||||
|
||||
<p>
|
||||
Elements can be <em>preserved</em>, meaning that they will not be
|
||||
disturbed even as their attributes, children, or siblings
|
||||
change. In this example, when you press the X++ button, the CSS
|
||||
animation continues uninterrupted.
|
||||
</p>
|
||||
|
||||
|
||||
X={{x}}<br>
|
||||
<div class="spinner" style="-webkit-animation: {{spinAnim}} 2s infinite linear">
|
||||
X={{x}}
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" class="spinforward" {{spinForwardChecked}}>
|
||||
Spin Forward
|
||||
</div>
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="constantDemo">
|
||||
<h2>Constant regions</h2>
|
||||
|
||||
<div>
|
||||
<input type="button" value="X++" class="x"> <br>
|
||||
<input type="checkbox" class="remove" which="1" {{checked 1}}>
|
||||
Remove map 1<br>
|
||||
<input type="checkbox" class="remove" which="2" {{checked 2}}>
|
||||
Remove map 2
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<p>
|
||||
Parts of a template can be marked as <em>constant</em>, meaning
|
||||
that Meteor will leave the entire region alone (even as its
|
||||
siblings change.) This is great for embedding non-Meteor
|
||||
widgets. Try scrolling the two Google Maps embeds below. When you
|
||||
press X++, the maps stay where they are.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Try using the checkboxes to remove either or both of the
|
||||
maps. When you remove a map, Spark tracks the <em>identity</em> of
|
||||
the constant regions so that it knows which DOM nodes to keep and
|
||||
which DOM nodes to throw away. In the case of the Handlebars
|
||||
package, the identity is based on the actual template call stack
|
||||
that rendered the constant region.
|
||||
</p>
|
||||
|
||||
X={{x}}<br>
|
||||
|
||||
{{#if show 1}}
|
||||
{{#constant}}
|
||||
<div style="float: left; padding-right: 20px;">
|
||||
<iframe width="290" height="290" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=140+10th+Street,+San+Francisco,+CA&aq=0&oq=140+10th+s&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=140+10th+St,+San+Francisco,+California+94103&t=m&ll=37.774921,-122.415419&spn=0.013569,0.017252&z=14&iwloc=A&output=embed"></iframe><br /><small><a href="https://maps.google.com/maps?f=q&source=embed&hl=en&geocode=&q=140+10th+Street,+San+Francisco,+CA&aq=0&oq=140+10th+s&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=140+10th+St,+San+Francisco,+California+94103&t=m&ll=37.774921,-122.415419&spn=0.013569,0.017252&z=14&iwloc=A" style="color:#0000FF;text-align:left">View Larger Map</a></small>
|
||||
</div>
|
||||
{{/constant}}
|
||||
{{/if}}
|
||||
|
||||
{{#if show 2}}
|
||||
{{#constant}}
|
||||
<div>
|
||||
<iframe width="290" height="290" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=880+Harrison+Street,+San+Francisco,+CA&aq=0&oq=880+harrison&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=880+Harrison+St,+San+Francisco,+California+94107&t=m&ll=37.779534,-122.411213&spn=0.013568,0.01708&z=14&iwloc=A&output=embed"></iframe><br /><small><a href="https://maps.google.com/maps?f=q&source=embed&hl=en&geocode=&q=880+Harrison+Street,+San+Francisco,+CA&aq=0&oq=880+harrison&sll=37.7577,-122.4376&sspn=0.166931,0.329247&ie=UTF8&hq=&hnear=880+Harrison+St,+San+Francisco,+California+94107&t=m&ll=37.779534,-122.411213&spn=0.013568,0.01708&z=14&iwloc=A" style="color:#0000FF;text-align:left">View Larger Map</a></small>
|
||||
</div>
|
||||
{{/constant}}
|
||||
{{/if}}
|
||||
|
||||
<div class="clearboth"> </div>
|
||||
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="stateDemo">
|
||||
<h2>Template callbacks</h2>
|
||||
|
||||
<p>
|
||||
<input type="button" value="X++" class="x">
|
||||
<input type="button" value="Y++" class="y">
|
||||
<input type="button" value="Z++" class="z">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can get a <em>created</em> callback when a template is
|
||||
initially rendered; a <em>rendered</em> when a template is placed on
|
||||
the screen and when any part of the template is redrawn; and
|
||||
a <em>destroyed</em> callback when a template is taken across the
|
||||
screen. All of these callbacks receive a common <em>template state
|
||||
object</em> in 'this' which allows you to attach data to each
|
||||
particular instance of a template.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this case, <em>created</em> is used to create a new JavaScript
|
||||
timer that updates the text of a <span> element every
|
||||
second. <em>rendered</em> is used to find the <span> when it
|
||||
appears on the screen, and update the pointer when the
|
||||
<span> is redraw (say, when you press Y++ — since it
|
||||
is not marked to be preserved.) <em>destroyed</em> is used to cancel
|
||||
the timer when the template goes off the screen.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The template state is used to hold the current time count and a
|
||||
reference to the <span> object to update. That's why there
|
||||
can be multiple copies of the same template, each with a different
|
||||
value for the counter.
|
||||
</p>
|
||||
|
||||
X={{x}}<br>
|
||||
<input type="button" value="Create a timer" class="create"><br>
|
||||
{{#each timers}}
|
||||
<div>
|
||||
{{> timer}}
|
||||
Z={{z}}
|
||||
</div>
|
||||
{{/each}}
|
||||
X={{x}}
|
||||
</template>
|
||||
|
||||
<template name="timer">
|
||||
<span class="elapsed"></span>
|
||||
<input type="button" value="Reset" class="reset">
|
||||
<input type="button" value="Delete" class="delete">
|
||||
Y={{y}}
|
||||
</template>
|
||||
|
||||
<template name="d3Demo">
|
||||
<h2>Simple d3.js integration</h2>
|
||||
<p>
|
||||
Meteor fits naturally with the popular d3.js data visualization
|
||||
library by Michael Bostock. Just set up d3 from your
|
||||
template's <em>rendered</em> callback. With Meteor, you can pass
|
||||
data directly out of a Mongo query into d3, and your d3
|
||||
visualization will update in realtime, with no extra code! Try
|
||||
opening this page in two browser windows.
|
||||
</p>
|
||||
|
||||
{{> circles left}}
|
||||
{{> circles right}}
|
||||
<div class="clearboth"> </div>
|
||||
|
||||
</template>
|
||||
|
||||
<template name="circles">
|
||||
<div class="circles">
|
||||
{{#constant}}
|
||||
<svg width="272" height="272"></svg>
|
||||
{{/constant}}
|
||||
<br>
|
||||
{{count}} circles<br>
|
||||
<input type="button" value="Add" class="add">
|
||||
<input type="button" value="Remove" class="remove" {{disabled}}>
|
||||
<input type="button" value="Scram" class="scram">
|
||||
<input type="button" value="Clear" class="clear">
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,273 +0,0 @@
|
||||
Timers = new Mongo.Collection(null);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (! Session.get("x")) {
|
||||
Session.set("x", 1);
|
||||
}
|
||||
|
||||
if (! Session.get("y")) {
|
||||
Session.set("y", 1);
|
||||
}
|
||||
|
||||
if (! Session.get("z")) {
|
||||
Session.set("z", 1);
|
||||
}
|
||||
|
||||
Template.preserveDemo.x =
|
||||
Template.constantDemo.x =
|
||||
Template.stateDemo.x =
|
||||
function () {
|
||||
return Session.get("x");
|
||||
};
|
||||
|
||||
Template.timer.y = function () {
|
||||
return Session.get("y");
|
||||
};
|
||||
|
||||
Template.stateDemo.z =
|
||||
function () {
|
||||
return Session.get("z");
|
||||
};
|
||||
|
||||
Template.page.events({
|
||||
'click input.x': function () {
|
||||
Session.set("x", Session.get("x") + 1);
|
||||
},
|
||||
|
||||
'click input.y': function () {
|
||||
Session.set("y", Session.get("y") + 1);
|
||||
},
|
||||
|
||||
'click input.z': function () {
|
||||
Session.set("z", Session.get("z") + 1);
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof Session.get("spinForward") !== 'boolean') {
|
||||
Session.set("spinForward", true);
|
||||
}
|
||||
|
||||
Template.preserveDemo.preserve([ '.spinner', '.spinforward' ]);
|
||||
|
||||
Template.preserveDemo.spinForwardChecked = function () {
|
||||
return Session.get('spinForward') ? 'checked' : '';
|
||||
};
|
||||
|
||||
Template.preserveDemo.spinAnim = function () {
|
||||
return Session.get('spinForward') ? 'spinForward' : 'spinBackward';
|
||||
};
|
||||
|
||||
Template.preserveDemo.events({
|
||||
'change .spinforward' : function (event) {
|
||||
Session.set('spinForward', event.currentTarget.checked);
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Template.constantDemo.checked = function (which) {
|
||||
return Session.get('mapchecked' + which) ? 'checked' : '';
|
||||
};
|
||||
|
||||
Template.constantDemo.show = function (which) {
|
||||
return ! Session.get('mapchecked' + which);
|
||||
};
|
||||
|
||||
Template.constantDemo.events({
|
||||
'change .remove' : function (event) {
|
||||
var tgt = event.currentTarget;
|
||||
Session.set('mapchecked' + tgt.getAttribute("which"), tgt.checked);
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Template.stateDemo.events({
|
||||
'click .create': function () {
|
||||
Timers.insert({});
|
||||
}
|
||||
});
|
||||
|
||||
Template.stateDemo.timers = function () {
|
||||
return Timers.find();
|
||||
};
|
||||
|
||||
Template.timer.events({
|
||||
'click .reset': function (event, template) {
|
||||
template.elapsed = 0;
|
||||
updateTimer(template);
|
||||
},
|
||||
'click .delete': function () {
|
||||
Timers.remove(this._id);
|
||||
}
|
||||
});
|
||||
|
||||
var updateTimer = function (timer) {
|
||||
timer.node.innerHTML = timer.elapsed + " second" +
|
||||
((timer.elapsed === 1) ? "" : "s");
|
||||
};
|
||||
|
||||
Template.timer.onCreated(function () {
|
||||
var self = this;
|
||||
self.elapsed = 0;
|
||||
self.node = null;
|
||||
});
|
||||
|
||||
Template.timer.onRendered(function () {
|
||||
var self = this;
|
||||
self.node = this.find(".elapsed");
|
||||
updateTimer(self);
|
||||
|
||||
if (! self.timer) {
|
||||
var tick = function () {
|
||||
self.elapsed++;
|
||||
self.timer = setTimeout(tick, 1000);
|
||||
updateTimer(self);
|
||||
};
|
||||
tick();
|
||||
}
|
||||
});
|
||||
|
||||
Template.timer.onDestroyed(function () {
|
||||
clearInterval(this.timer);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Template.d3Demo.left = function () {
|
||||
return { group: "left" };
|
||||
};
|
||||
|
||||
Template.d3Demo.right = function () {
|
||||
return { group: "right" };
|
||||
};
|
||||
|
||||
Template.circles.events({
|
||||
'mousedown circle': function (evt, template) {
|
||||
Session.set("selectedCircle:" + this.group, evt.currentTarget.id);
|
||||
},
|
||||
'click .add': function () {
|
||||
Circles.insert({x: Random.fraction(), y: Random.fraction(),
|
||||
r: Random.fraction() * .1 + .02,
|
||||
color: {
|
||||
r: Random.fraction(),
|
||||
g: Random.fraction(),
|
||||
b: Random.fraction()
|
||||
},
|
||||
group: this.group
|
||||
});
|
||||
},
|
||||
'click .remove': function () {
|
||||
var selected = Session.get("selectedCircle:" + this.group);
|
||||
if (selected) {
|
||||
Circles.remove(selected);
|
||||
Session.set("selectedCircle:" + this.group, null);
|
||||
}
|
||||
},
|
||||
'click .scram': function () {
|
||||
Circles.find({group: this.group}).forEach(function (r) {
|
||||
Circles.update(r._id, {
|
||||
$set: {
|
||||
x: Random.fraction(), y: Random.fraction(), r: Random.fraction() * .1 + .02
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
'click .clear': function () {
|
||||
Circles.remove({group: this.group});
|
||||
}
|
||||
});
|
||||
|
||||
var colorToString = function (color) {
|
||||
var f = function (x) { return Math.floor(x * 256); };
|
||||
return "rgb(" + f(color.r) + "," +
|
||||
+ f(color.g) + "," + + f(color.b) + ")";
|
||||
};
|
||||
|
||||
Template.circles.count = function () {
|
||||
return Circles.find({group: this.group}).count();
|
||||
};
|
||||
|
||||
Template.circles.disabled = function () {
|
||||
return Session.get("selectedCircle:" + this.group) ?
|
||||
'' : 'disabled';
|
||||
};
|
||||
|
||||
Template.circles.onCreated(function () {
|
||||
});
|
||||
|
||||
Template.circles.onRendered(function () {
|
||||
var self = this;
|
||||
self.node = self.find("svg");
|
||||
|
||||
var data = self.data;
|
||||
|
||||
if (! self.handle) {
|
||||
d3.select(self.node).append("rect");
|
||||
self.handle = Deps.autorun(function () {
|
||||
var circle = d3.select(self.node).selectAll("circle")
|
||||
.data(Circles.find({group: data.group}).fetch(),
|
||||
function (d) { return d._id; });
|
||||
|
||||
circle.enter().append("circle")
|
||||
.attr("id", function (d) {
|
||||
return d._id;
|
||||
})
|
||||
.attr("cx", function (d) {
|
||||
return d.x * 272;
|
||||
})
|
||||
.attr("cy", function (d) {
|
||||
return d.y * 272;
|
||||
})
|
||||
.attr("r", 50)
|
||||
.style("fill", function (d) {
|
||||
return colorToString(d.color);
|
||||
})
|
||||
.style("opacity", 0);
|
||||
|
||||
circle.transition()
|
||||
.duration(250)
|
||||
.attr("cx", function (d) {
|
||||
return d.x * 272;
|
||||
})
|
||||
.attr("cy", function (d) {
|
||||
return d.y * 272;
|
||||
})
|
||||
.attr("r", function (d) {
|
||||
return d.r * 272;
|
||||
})
|
||||
.style("fill", function (d) {
|
||||
return colorToString(d.color);
|
||||
})
|
||||
.style("opacity", .9)
|
||||
.ease("cubic-out");
|
||||
|
||||
circle.exit().transition()
|
||||
.duration(250)
|
||||
.attr("r", 0)
|
||||
.remove();
|
||||
|
||||
var selectionId = Session.get("selectedCircle:" + data.group);
|
||||
var s = selectionId && Circles.findOne(selectionId);
|
||||
var rect = d3.select(self.node).select("rect");
|
||||
if (s)
|
||||
rect.attr("x", (s.x - s.r) * 272)
|
||||
.attr("y", (s.y - s.r) * 272)
|
||||
.attr("width", s.r * 2 * 272)
|
||||
.attr("height", s.r * 2 * 272)
|
||||
.attr("display", '')
|
||||
.style("fill", "none")
|
||||
.style("stroke", "red")
|
||||
.style("stroke-width", 3);
|
||||
else
|
||||
rect.attr("display", 'none');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Template.circles.onDestroyed(function () {
|
||||
this.handle && this.handle.stop();
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
Circles = new Mongo.Collection("circles");
|
||||
@@ -1,7 +0,0 @@
|
||||
# This file contains information which helps Meteor properly upgrade your
|
||||
# app when you run 'meteor update'. You should check it into version control
|
||||
# with your project.
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
1
examples/other/wordplay/.meteor/.gitignore
vendored
1
examples/other/wordplay/.meteor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,8 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
insecure
|
||||
jquery
|
||||
@@ -1,2 +0,0 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +0,0 @@
|
||||
METEOR@0.9.4
|
||||
@@ -1,51 +0,0 @@
|
||||
application-configuration@1.0.3
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
@@ -1,12 +0,0 @@
|
||||
TODOS
|
||||
strip spaces on input box
|
||||
focus input on game start
|
||||
styling
|
||||
eliminate extra divs
|
||||
|
||||
POSSIBLE EXTENSIONS
|
||||
publish remaining words at end of game
|
||||
UI that works on touch devices sans keyboard
|
||||
spinny while word is getting scored
|
||||
support clicking on board instead of text box
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
background-color: #f4f4f4;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* base styles */
|
||||
|
||||
input {
|
||||
height: 50px;
|
||||
width: 300px;
|
||||
font-size: 2em;
|
||||
border: 2px solid black;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
position: relative;
|
||||
bottom: 3px;
|
||||
margin: 10px;
|
||||
height: 50px;
|
||||
background-color:#E6EFC2;
|
||||
border:1px solid #dedede;
|
||||
font-weight:bold;
|
||||
cursor:pointer;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color:#D6DFb2;
|
||||
border:1px solid #C6D880;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color:#529214;
|
||||
border:1px solid #529214;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
/*******/
|
||||
|
||||
#main {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#left {
|
||||
float: left;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
#right {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#clock {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
#board {
|
||||
margin: auto;
|
||||
border:4px solid #999999;
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
padding:2px;
|
||||
|
||||
width:400px;
|
||||
height:400px;
|
||||
background-color:#999999;
|
||||
}
|
||||
|
||||
.square {
|
||||
cursor: pointer;
|
||||
width:84px;
|
||||
height:84px;
|
||||
border:4px solid #eeeee8;
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
margin: 4px;
|
||||
float:left;
|
||||
text-align: center;
|
||||
background-color:#eeeee8;
|
||||
font-size: 65px;
|
||||
}
|
||||
|
||||
.square.last_in_path {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.square.in_path {
|
||||
color: #990000;
|
||||
}
|
||||
|
||||
#login {
|
||||
margin: 100px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#login .error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#lobby {
|
||||
margin: 100px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#postgame {
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#scratchpad {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#scratchpad input {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
#scratchpad h1 {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#scores {
|
||||
float: left;
|
||||
width: 100%;
|
||||
background-color: #eeeee8;
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#scores .player {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#scores .header {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
#scores .unnamed {
|
||||
color: #444;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#scores .winner {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
#scores .winner_text {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#scores .word {
|
||||
float: left;
|
||||
font-size: 1.25em;
|
||||
padding: 0.25em;
|
||||
margin: 0.5em;
|
||||
border: 1px solid #030;
|
||||
}
|
||||
|
||||
#scores .word.good {
|
||||
background-color: #0a0;
|
||||
}
|
||||
|
||||
#scores .word.bad {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
#scores .word span.score {
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
#scores .word.bad span.score {
|
||||
background-image: 'circle-ball-dark-antialiased.gif';
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<head>
|
||||
<title>Word play!</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> page}}
|
||||
</body>
|
||||
|
||||
<template name="page">
|
||||
<div id="main">
|
||||
<div id="left">
|
||||
{{> board }}
|
||||
</div>
|
||||
<div id="right">
|
||||
{{> lobby }}
|
||||
{{> scratchpad }}
|
||||
{{> postgame }}
|
||||
{{> scores }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="board">
|
||||
<div id="clock">
|
||||
{{ clock }}
|
||||
</div>
|
||||
<div id="board">
|
||||
<div>
|
||||
<div class="square {{ selected 0 }}">{{ square 0 }}</div>
|
||||
<div class="square {{ selected 1 }}">{{ square 1 }}</div>
|
||||
<div class="square {{ selected 2 }}">{{ square 2 }}</div>
|
||||
<div class="square {{ selected 3 }}">{{ square 3 }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="square {{ selected 4 }}">{{ square 4 }}</div>
|
||||
<div class="square {{ selected 5 }}">{{ square 5 }}</div>
|
||||
<div class="square {{ selected 6 }}">{{ square 6 }}</div>
|
||||
<div class="square {{ selected 7 }}">{{ square 7 }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="square {{ selected 8 }}">{{ square 8 }}</div>
|
||||
<div class="square {{ selected 9 }}">{{ square 9 }}</div>
|
||||
<div class="square {{ selected 10 }}">{{ square 10 }}</div>
|
||||
<div class="square {{ selected 11 }}">{{ square 11 }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="square {{ selected 12 }}">{{ square 12 }}</div>
|
||||
<div class="square {{ selected 13 }}">{{ square 13 }}</div>
|
||||
<div class="square {{ selected 14 }}">{{ square 14 }}</div>
|
||||
<div class="square {{ selected 15 }}">{{ square 15 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="lobby">
|
||||
<div>
|
||||
{{#if show }}
|
||||
<div id="lobby">
|
||||
<h1>What's your name?</h1>
|
||||
<input id="myname" type="text" />
|
||||
{{#if count}}
|
||||
<h1>{{count}} other players are in the lobby:</h1>
|
||||
{{#each waiting }}
|
||||
<div class="player">{{name}}</div>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
<div>
|
||||
<button id="startgame" class="startgame" {{disabled}}>
|
||||
{{#if count}} It's on! {{else}} Play solo {{/if}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="scratchpad">
|
||||
{{#if show}}
|
||||
<div id="scratchpad">
|
||||
<input id="scratchpad_input" type="text" />
|
||||
<button name="submit" class="submit">Submit</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
<template name="postgame">
|
||||
<div>
|
||||
{{#if show}}
|
||||
<div id="postgame">
|
||||
<button name="backtolobby" class="lobby">Back to lobby</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="scores">
|
||||
<div>
|
||||
{{#if show}}
|
||||
<div id="scores">
|
||||
{{#each players}}
|
||||
{{> player }}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="player">
|
||||
<div class="player">
|
||||
<div class="header {{winner}}">
|
||||
{{#if name}}
|
||||
{{name}}
|
||||
{{else}}
|
||||
<span class="unnamed">no name</span>
|
||||
{{/if}}
|
||||
<span class="score">{{total_score}}</span>
|
||||
{{#if winner}}
|
||||
<span class="winner_text">Winner!</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{> words}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="words">
|
||||
<div class="words">
|
||||
{{#each words}}
|
||||
<div id="word_{{_id}}" class="word {{state}}">
|
||||
<span class="score">
|
||||
{{score}}
|
||||
</span>
|
||||
{{word}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,252 +0,0 @@
|
||||
////////// Main client application logic //////////
|
||||
|
||||
//////
|
||||
////// Utility functions
|
||||
//////
|
||||
|
||||
var player = function () {
|
||||
return Players.findOne(Session.get('player_id'));
|
||||
};
|
||||
|
||||
var game = function () {
|
||||
var me = player();
|
||||
return me && me.game_id && Games.findOne(me.game_id);
|
||||
};
|
||||
|
||||
var set_selected_positions = function (word) {
|
||||
var paths = paths_for_word(game().board, word.toUpperCase());
|
||||
var in_a_path = [];
|
||||
var last_in_a_path = [];
|
||||
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
in_a_path = in_a_path.concat(paths[i]);
|
||||
last_in_a_path.push(paths[i].slice(-1)[0]);
|
||||
}
|
||||
|
||||
for (var pos = 0; pos < 16; pos++) {
|
||||
if (_.indexOf(last_in_a_path, pos) !== -1)
|
||||
Session.set('selected_' + pos, 'last_in_path');
|
||||
else if (_.indexOf(in_a_path, pos) !== -1)
|
||||
Session.set('selected_' + pos, 'in_path');
|
||||
else
|
||||
Session.set('selected_' + pos, false);
|
||||
}
|
||||
};
|
||||
|
||||
var clear_selected_positions = function () {
|
||||
for (var pos = 0; pos < 16; pos++)
|
||||
Session.set('selected_' + pos, false);
|
||||
};
|
||||
|
||||
//////
|
||||
////// lobby template: shows everyone not currently playing, and
|
||||
////// offers a button to start a fresh game.
|
||||
//////
|
||||
|
||||
Template.lobby.helpers({
|
||||
show: function () {
|
||||
// only show lobby if we're not in a game
|
||||
return !game();
|
||||
},
|
||||
|
||||
waiting: function () {
|
||||
var players = Players.find({_id: {$ne: Session.get('player_id')},
|
||||
name: {$ne: ''},
|
||||
game_id: {$exists: false}});
|
||||
|
||||
return players;
|
||||
},
|
||||
|
||||
count: function () {
|
||||
var players = Players.find({_id: {$ne: Session.get('player_id')},
|
||||
name: {$ne: ''},
|
||||
game_id: {$exists: false}});
|
||||
|
||||
return players.count();
|
||||
},
|
||||
|
||||
disabled: function () {
|
||||
var me = player();
|
||||
if (me && me.name)
|
||||
return '';
|
||||
return 'disabled';
|
||||
}
|
||||
});
|
||||
|
||||
var trim = function (string) { return string.replace(/^\s+|\s+$/g, ''); };
|
||||
|
||||
Template.lobby.events({
|
||||
'keyup input#myname': function (evt) {
|
||||
var name = trim($('#lobby input#myname').val());
|
||||
Players.update(Session.get('player_id'), {$set: {name: name}});
|
||||
},
|
||||
'click button.startgame': function () {
|
||||
Meteor.call('start_new_game');
|
||||
}
|
||||
});
|
||||
|
||||
//////
|
||||
////// board template: renders the board and the clock given the
|
||||
////// current game. if there is no game, show a splash screen.
|
||||
//////
|
||||
var SPLASH = ['','','','',
|
||||
'W', 'O', 'R', 'D',
|
||||
'P', 'L', 'A', 'Y',
|
||||
'','','',''];
|
||||
|
||||
Template.board.helpers({
|
||||
square: function (i) {
|
||||
var g = game();
|
||||
return g && g.board && g.board[i] || SPLASH[i];
|
||||
},
|
||||
|
||||
selected: function (i) {
|
||||
return Session.get('selected_' + i);
|
||||
},
|
||||
|
||||
clock: function () {
|
||||
var clock = game() && game().clock;
|
||||
|
||||
if (!clock || clock === 0)
|
||||
return;
|
||||
|
||||
// format into M:SS
|
||||
var min = Math.floor(clock / 60);
|
||||
var sec = clock % 60;
|
||||
return min + ':' + (sec < 10 ? ('0' + sec) : sec);
|
||||
}
|
||||
});
|
||||
|
||||
Template.board.events({
|
||||
'click .square': function (evt) {
|
||||
var textbox = $('#scratchpad input');
|
||||
// Note: Getting the letter out of the DOM is kind of a hack
|
||||
var letter = evt.target.textContent || evt.target.innerText;
|
||||
textbox.val(textbox.val() + letter);
|
||||
textbox.focus();
|
||||
}
|
||||
});
|
||||
|
||||
//////
|
||||
////// scratchpad is where we enter new words.
|
||||
//////
|
||||
|
||||
Template.scratchpad.helpers({
|
||||
show: function () {
|
||||
return game() && game().clock > 0;
|
||||
}
|
||||
});
|
||||
|
||||
Template.scratchpad.events({
|
||||
'click button, keyup input': function (evt) {
|
||||
var textbox = $('#scratchpad input');
|
||||
// if we clicked the button or hit enter
|
||||
if ((evt.type === "click" || (evt.type === "keyup" && evt.which === 13))
|
||||
&& textbox.val()) {
|
||||
var word_id = Words.insert({player_id: Session.get('player_id'),
|
||||
game_id: game() && game()._id,
|
||||
word: textbox.val().toUpperCase(),
|
||||
state: 'pending'});
|
||||
Meteor.call('score_word', word_id);
|
||||
textbox.val('');
|
||||
textbox.focus();
|
||||
clear_selected_positions();
|
||||
} else {
|
||||
set_selected_positions(textbox.val());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.postgame.helpers({
|
||||
show: function () {
|
||||
return game() && game().clock === 0;
|
||||
}
|
||||
});
|
||||
|
||||
Template.postgame.events({
|
||||
'click button': function (evt) {
|
||||
Players.update(Session.get('player_id'), {$set: {game_id: null}});
|
||||
}
|
||||
});
|
||||
|
||||
//////
|
||||
////// scores shows everyone's score and word list.
|
||||
//////
|
||||
|
||||
Template.scores.helpers({
|
||||
show: function () {
|
||||
return !!game();
|
||||
},
|
||||
|
||||
players: function () {
|
||||
return game() && game().players;
|
||||
}
|
||||
});
|
||||
|
||||
Template.player.helpers({
|
||||
winner: function () {
|
||||
var g = game();
|
||||
if (g.winners && _.include(g.winners, this._id))
|
||||
return 'winner';
|
||||
return '';
|
||||
},
|
||||
|
||||
total_score: function () {
|
||||
var words = Words.find({game_id: game() && game()._id,
|
||||
player_id: this._id});
|
||||
|
||||
var score = 0;
|
||||
words.forEach(function (word) {
|
||||
if (word.score)
|
||||
score += word.score;
|
||||
});
|
||||
return score;
|
||||
}
|
||||
});
|
||||
|
||||
Template.words.helpers({
|
||||
words: function () {
|
||||
return Words.find({game_id: game() && game()._id,
|
||||
player_id: this._id});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//////
|
||||
////// Initialization
|
||||
//////
|
||||
|
||||
Meteor.startup(function () {
|
||||
// Allocate a new player id.
|
||||
//
|
||||
// XXX this does not handle hot reload. In the reload case,
|
||||
// Session.get('player_id') will return a real id. We should check for
|
||||
// a pre-existing player, and if it exists, make sure the server still
|
||||
// knows about us.
|
||||
var player_id = Players.insert({name: '', idle: false});
|
||||
Session.set('player_id', player_id);
|
||||
|
||||
// subscribe to all the players, the game i'm in, and all
|
||||
// the words in that game.
|
||||
Tracker.autorun(function () {
|
||||
Meteor.subscribe('players');
|
||||
|
||||
if (Session.get('player_id')) {
|
||||
var me = player();
|
||||
if (me && me.game_id) {
|
||||
Meteor.subscribe('games', me.game_id);
|
||||
Meteor.subscribe('words', me.game_id, Session.get('player_id'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// send keepalives so the server can tell when we go away.
|
||||
//
|
||||
// XXX this is not a great idiom. meteor server does not yet have a
|
||||
// way to expose connection status to user code. Once it does, this
|
||||
// code can go away.
|
||||
Meteor.setInterval(function() {
|
||||
if (Meteor.status().connected)
|
||||
Meteor.call('keepalive', Session.get('player_id'));
|
||||
}, 20*1000);
|
||||
});
|
||||
@@ -1,158 +0,0 @@
|
||||
////////// Shared code (client and server) //////////
|
||||
|
||||
Games = new Mongo.Collection('games');
|
||||
// { board: ['A','I',...], clock: 60,
|
||||
// players: [{player_id, name}], winners: [player_id] }
|
||||
|
||||
Words = new Mongo.Collection('words');
|
||||
// {player_id: 10, game_id: 123, word: 'hello', state: 'good', score: 4}
|
||||
|
||||
Players = new Mongo.Collection('players');
|
||||
// {name: 'matt', game_id: 123}
|
||||
|
||||
// 6 faces per die, 16 dice. Q really means Qu.
|
||||
var DICE = ['PCHOAS', 'OATTOW', 'LRYTTE', 'VTHRWE',
|
||||
'EGHWNE', 'SEOTIS', 'ANAEEG', 'IDSYTT',
|
||||
'MTOICU', 'AFPKFS', 'XLDERI', 'ENSIEU',
|
||||
'YLDEVR', 'ZNRNHL', 'NMIQHU', 'OBBAOJ'];
|
||||
|
||||
var DICTIONARY = null;
|
||||
|
||||
// board is an array of length 16, in row-major order. ADJACENCIES
|
||||
// lists the board positions adjacent to each board position.
|
||||
var ADJACENCIES = [
|
||||
[1,4,5],
|
||||
[0,2,4,5,6],
|
||||
[1,3,5,6,7],
|
||||
[2,6,7],
|
||||
[0,1,5,8,9],
|
||||
[0,1,2,4,6,8,9,10],
|
||||
[1,2,3,5,7,9,10,11],
|
||||
[2,3,6,10,11],
|
||||
[4,5,9,12,13],
|
||||
[4,5,6,8,10,12,13,14],
|
||||
[5,6,7,9,11,13,14,15],
|
||||
[6,7,10,14,15],
|
||||
[8,9,13],
|
||||
[8,9,10,12,14],
|
||||
[9,10,11,13,15],
|
||||
[10,11,14]
|
||||
];
|
||||
|
||||
// generate a new random selection of letters.
|
||||
new_board = function () {
|
||||
var board = [];
|
||||
var i;
|
||||
|
||||
// pick random letter from each die
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
board[i] = Random.choice(DICE[i]);
|
||||
}
|
||||
|
||||
// knuth shuffle
|
||||
for (i = 15; i > 0; i -= 1) {
|
||||
var j = Math.floor(Math.random() * (i + 1));
|
||||
var tmp = board[i];
|
||||
board[i] = board[j];
|
||||
board[j] = tmp;
|
||||
}
|
||||
|
||||
return board;
|
||||
};
|
||||
|
||||
// returns an array of valid paths to make the specified word on the
|
||||
// board. each path is an array of board positions 0-15. a valid
|
||||
// path can use each position only once, and each position must be
|
||||
// adjacent to the previous position.
|
||||
paths_for_word = function (board, word) {
|
||||
var valid_paths = [];
|
||||
|
||||
var check_path = function (word, path, positions_to_try) {
|
||||
// base case: the whole word has been consumed. path is valid.
|
||||
if (word.length === 0) {
|
||||
valid_paths.push(path);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, try to match each available position against the
|
||||
// first letter of the word, avoiding any positions that are
|
||||
// already used by the path. for each of those matches, descend
|
||||
// recursively, passing the remainder of the word, the accumulated
|
||||
// path, and the positions adjacent to the match.
|
||||
|
||||
for (var i = 0; i < positions_to_try.length; i++) {
|
||||
var pos = positions_to_try[i];
|
||||
if (board[pos] === word[0] && _.indexOf(path, pos) === -1)
|
||||
check_path(word.slice(1), // cdr of word
|
||||
path.concat([pos]), // append matching loc to path
|
||||
ADJACENCIES[pos]); // only look at surrounding tiles
|
||||
}
|
||||
};
|
||||
|
||||
// start recursive search w/ full word, empty path, and all tiles
|
||||
// available for the first letter.
|
||||
check_path(word, [], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]);
|
||||
|
||||
return valid_paths;
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
score_word: function (word_id) {
|
||||
check(word_id, String);
|
||||
var word = Words.findOne(word_id);
|
||||
var game = Games.findOne(word.game_id);
|
||||
|
||||
// client and server can both check that the game has time remaining, and
|
||||
// that the word is at least three chars, isn't already used, and is
|
||||
// possible to make on the board.
|
||||
if (game.clock === 0
|
||||
|| !word.word
|
||||
|| word.word.length < 3
|
||||
|| Words.find({game_id: word.game_id, word: word.word}).count() > 1
|
||||
|| paths_for_word(game.board, word.word).length === 0) {
|
||||
Words.update(word._id, {$set: {score: 0, state: 'bad'}});
|
||||
return;
|
||||
}
|
||||
|
||||
// now only on the server, check against dictionary and score it.
|
||||
if (Meteor.isServer) {
|
||||
if (_.has(DICTIONARY, word.word.toLowerCase())) {
|
||||
var score = Math.pow(2, word.word.length - 3);
|
||||
Words.update(word._id, {$set: {score: score, state: 'good'}});
|
||||
} else {
|
||||
Words.update(word._id, {$set: {score: 0, state: 'bad'}});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (Meteor.isServer) {
|
||||
DICTIONARY = {};
|
||||
_.each(Assets.getText("enable2k.txt").split("\n"), function (line) {
|
||||
// Skip blanks and comment lines
|
||||
if (line && line.indexOf("//") !== 0) {
|
||||
DICTIONARY[line] = true;
|
||||
}
|
||||
});
|
||||
|
||||
// publish all the non-idle players.
|
||||
Meteor.publish('players', function () {
|
||||
return Players.find({idle: false});
|
||||
});
|
||||
|
||||
// publish single games
|
||||
Meteor.publish('games', function (id) {
|
||||
check(id, String);
|
||||
return Games.find({_id: id});
|
||||
});
|
||||
|
||||
// publish all my words and opponents' words that the server has
|
||||
// scored as good.
|
||||
Meteor.publish('words', function (game_id, player_id) {
|
||||
check(game_id, String);
|
||||
check(player_id, String);
|
||||
return Words.find({$or: [{game_id: game_id, state: 'good'},
|
||||
{player_id: player_id}]});
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 691 B |
@@ -1,70 +0,0 @@
|
||||
////////// Server only logic //////////
|
||||
|
||||
Meteor.methods({
|
||||
start_new_game: function () {
|
||||
// create a new game w/ fresh board
|
||||
var game_id = Games.insert({board: new_board(),
|
||||
clock: 120});
|
||||
|
||||
// move everyone who is ready in the lobby to the game
|
||||
Players.update({game_id: null, idle: false, name: {$ne: ''}},
|
||||
{$set: {game_id: game_id}},
|
||||
{multi: true});
|
||||
// Save a record of who is in the game, so when they leave we can
|
||||
// still show them.
|
||||
var p = Players.find({game_id: game_id},
|
||||
{fields: {_id: true, name: true}}).fetch();
|
||||
Games.update({_id: game_id}, {$set: {players: p}});
|
||||
|
||||
|
||||
// wind down the game clock
|
||||
var clock = 120;
|
||||
var interval = Meteor.setInterval(function () {
|
||||
clock -= 1;
|
||||
Games.update(game_id, {$set: {clock: clock}});
|
||||
|
||||
// end of game
|
||||
if (clock === 0) {
|
||||
// stop the clock
|
||||
Meteor.clearInterval(interval);
|
||||
// declare zero or more winners
|
||||
var scores = {};
|
||||
Words.find({game_id: game_id}).forEach(function (word) {
|
||||
if (!scores[word.player_id])
|
||||
scores[word.player_id] = 0;
|
||||
scores[word.player_id] += word.score;
|
||||
});
|
||||
var high_score = _.max(scores);
|
||||
var winners = [];
|
||||
_.each(scores, function (score, player_id) {
|
||||
if (score === high_score)
|
||||
winners.push(player_id);
|
||||
});
|
||||
Games.update(game_id, {$set: {winners: winners}});
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return game_id;
|
||||
},
|
||||
|
||||
|
||||
keepalive: function (player_id) {
|
||||
check(player_id, String);
|
||||
Players.update({_id: player_id},
|
||||
{$set: {last_keepalive: (new Date()).getTime(),
|
||||
idle: false}});
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.setInterval(function () {
|
||||
var now = (new Date()).getTime();
|
||||
var idle_threshold = now - 70*1000; // 70 sec
|
||||
var remove_threshold = now - 60*60*1000; // 1hr
|
||||
|
||||
Players.update({last_keepalive: {$lt: idle_threshold}},
|
||||
{$set: {idle: true}});
|
||||
|
||||
// XXX need to deal with people coming back!
|
||||
// Players.remove({$lt: {last_keepalive: remove_threshold}});
|
||||
|
||||
}, 30*1000);
|
||||
@@ -1,113 +0,0 @@
|
||||
require("./words.js");
|
||||
|
||||
var BOGGLE_DICE = ['pchoas', 'oattow', 'lrytte', 'vthrwe',
|
||||
'eghwne', 'seotis', 'anaeeg', 'idsytt',
|
||||
'mtoicu', 'afpkfs', 'xlderi', 'ensieu',
|
||||
'yldevr', 'znrnhl', 'nmiqhu', 'obbaoj'];
|
||||
|
||||
var FLAGS = [0x1, 0x2, 0x4, 0x8,
|
||||
0x10, 0x20, 0x40, 0x80,
|
||||
0x100, 0x200, 0x400, 0x800,
|
||||
0x1000, 0x2000, 0x4000, 0x8000];
|
||||
|
||||
var MASKS = {};
|
||||
|
||||
// generate masks for all one, two, three, and four-letter combinations
|
||||
var make_masks = function () {
|
||||
var mask_count = 0;
|
||||
|
||||
// recursive helper
|
||||
var check_mask = function (word, index, used) {
|
||||
for (var i = 0; i < 16; i += 1) {
|
||||
for (var j = 0; j < 6; j += 1) {
|
||||
// if die i is still available, and it has a letter that
|
||||
// matches what we need, we can make use of this.
|
||||
if (!(used & FLAGS[i]) && (BOGGLE_DICE[i][j] === word[index])) {
|
||||
if (word.length === index + 1) {
|
||||
// this is the end of the word, we have a valid mask!
|
||||
if (!MASKS[word])
|
||||
MASKS[word] = [];
|
||||
if (MASKS[word].indexOf(used | FLAGS[i]) === -1) {
|
||||
MASKS[word].push(used | FLAGS[i]);
|
||||
mask_count += 1;
|
||||
}
|
||||
// console.log("MASK", word, used | FLAGS[i]);
|
||||
} else {
|
||||
// descend into searching rest of word w/ remaining dice.
|
||||
check_mask(word,
|
||||
index + 1,
|
||||
used | FLAGS[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.stderr.write("CALCULATING MASKS FOR ");
|
||||
for (var a = 97; a <= 97; a += 1) {
|
||||
process.stderr.write(String.fromCharCode(a));
|
||||
check_mask(String.fromCharCode(a), 0, 0x0);
|
||||
for (var b = 97; b <= 122; b += 1) {
|
||||
check_mask(String.fromCharCode(a,b), 0, 0x0);
|
||||
for (var c = 97; c <= 122; c += 1) {
|
||||
check_mask(String.fromCharCode(a,b,c), 0, 0x0);
|
||||
for (var d = 97; d <= 122; d += 1) {
|
||||
check_mask(String.fromCharCode(a,b,c,d), 0, 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
process.stderr.write(" DONE [" + mask_count + " MASKS]\n");
|
||||
};
|
||||
|
||||
make_masks();
|
||||
|
||||
function check (word, index, used) {
|
||||
//console.log('CHECK', word, index, used);
|
||||
|
||||
var length;
|
||||
var masks;
|
||||
|
||||
// check up to 4 chars at a time
|
||||
length = (word.length - index > 4) ? 4 : word.length - index;
|
||||
masks = MASKS[word.slice(index, length + index)] || [];
|
||||
|
||||
for (var i = 0; i < masks.length; i += 1) {
|
||||
if (!(used & masks[i])) {
|
||||
// masks[i] has no overlap w/ tiles we already consumed.
|
||||
if (word.length === index + length)
|
||||
// we consumed the whole word.
|
||||
return true;
|
||||
else if (check(word, index + length, used | masks[i]))
|
||||
// some descendant consumed the whole word
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// none of the available masks returned true. there's no match.
|
||||
return false;
|
||||
};
|
||||
|
||||
var dict_len = DICTIONARY.length
|
||||
for (var i = 0; i < dict_len; i+=1) {
|
||||
var word = DICTIONARY[i];
|
||||
|
||||
// reject words that have q followed by non-u. those can't be made
|
||||
// in boggle. otherwise, strip the q -- our dictionary won't
|
||||
// include the u.
|
||||
|
||||
if (word.match(/q/)) {
|
||||
if (word.match(/q[^u]/)) {
|
||||
process.stderr.write('Q REJECT ' + word + '\n');
|
||||
continue;
|
||||
} else {
|
||||
word = word.replace('qu', 'q');
|
||||
process.stderr.write('Q REPLACED ' + word + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (check(word, 0, 0x0))
|
||||
console.log(word);
|
||||
else
|
||||
process.stderr.write('REJECT ' + DICTIONARY[i] + '\n');
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,7 +0,0 @@
|
||||
# This file contains a token that is unique to your project.
|
||||
# Check it into your repository along with the rest of this directory.
|
||||
# It can be used for purposes such as:
|
||||
# - ensuring you don't accidentally deploy one app on top of another
|
||||
# - providing package authors with aggregated statistics
|
||||
|
||||
wllgu394zq2.rrlkgpniscl
|
||||
@@ -1,18 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
autopublish
|
||||
insecure
|
||||
preserve-inputs
|
||||
accounts-ui
|
||||
less
|
||||
accounts-google
|
||||
accounts-github
|
||||
accounts-password
|
||||
accounts-facebook
|
||||
standard-app-packages
|
||||
facebook-config-ui
|
||||
github-config-ui
|
||||
google-config-ui
|
||||
@@ -1,2 +0,0 @@
|
||||
browser
|
||||
server
|
||||
@@ -1 +0,0 @@
|
||||
0.6.1
|
||||
@@ -1,131 +0,0 @@
|
||||
<head>
|
||||
<title>accounts-ui-viewer</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{> page}}
|
||||
</body>
|
||||
|
||||
<template name="radio">
|
||||
<span class="radio">
|
||||
<input id="{{key}}:{{value}}" {{maybeChecked}} type="radio" name="{{key}}" value="{{value}}" />
|
||||
<label for="{{key}}:{{value}}">{{label}}</label>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template name="button">
|
||||
<button>{{label}}</button>
|
||||
</template>
|
||||
|
||||
<template name="page">
|
||||
<div id="controlpane">
|
||||
<div class="group">
|
||||
<h3>Dropdown align edge:</h3>
|
||||
{{> radio key="alignRight" value="false" label="Left"}}
|
||||
{{> radio key="alignRight" value="true" label="Right"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Positioning:</h3>
|
||||
{{> radio key="positioning" value="relative" label="Relative"}}
|
||||
{{> radio key="positioning" value="absolute" label="Absolute"}}
|
||||
{{> radio key="positioning" value="floatRight" label="Float:right"}}
|
||||
{{> radio key="positioning" value="inline" label="Inline"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>How many third-party services?</h3>
|
||||
{{> radio key="numServices" value="0" label="0"}}
|
||||
{{> radio key="numServices" value="1" label="1"}}
|
||||
{{> radio key="numServices" value="2" label="2"}}
|
||||
{{> radio key="numServices" value="3" label="3"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Has password accounts?</h3>
|
||||
{{> radio key="hasPasswords" value="false" label="No"}}
|
||||
{{> radio key="hasPasswords" value="true" label="Yes"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Password sign-up fields:</h3>
|
||||
{{> radio key="signupFields" value="EMAIL_ONLY" label="Email"}}
|
||||
{{> radio key="signupFields" value="USERNAME_ONLY" label="Username"}}
|
||||
{{> radio key="signupFields" value="USERNAME_AND_EMAIL" label="Username & Email"}}
|
||||
{{> radio key="signupFields" value="USERNAME_AND_OPTIONAL_EMAIL" label="Username & Optional Email"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Fake-Configure:</h3>
|
||||
{{> button key="fakeConfig" value="facebook" label="Facebook"}}
|
||||
{{> button key="fakeConfig" value="github" label="GitHub"}}
|
||||
{{> button key="fakeConfig" value="google" label="Google"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Show Configure Dialog:</h3>
|
||||
{{> button key="showConfig" value="facebook" label="Facebook"}}
|
||||
{{> button key="showConfig" value="github" label="GitHub"}}
|
||||
{{> button key="showConfig" value="google" label="Google"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Unconfigure:</h3>
|
||||
{{> button key="unconfig" value="facebook" label="Facebook"}}
|
||||
{{> button key="unconfig" value="github" label="GitHub"}}
|
||||
{{> button key="unconfig" value="google" label="Google"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Messages:</h3>
|
||||
{{> button key="messages" value="error" label="Error"}}
|
||||
{{> button key="messages" value="info" label="Info"}}
|
||||
{{> button key="messages" value="clear" label="Clear"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Signing in/out</h3>
|
||||
{{> button key="sign" value="in" label="Fake sign-in"}}
|
||||
{{> button key="sign" value="out" label="Sign out"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Logged-out Views</h3>
|
||||
{{> button key="lov" value="signIn" label="Sign In"}}
|
||||
{{> button key="lov" value="createAccount" label="Create Account"}}
|
||||
{{> button key="lov" value="forgotPassword" label="Forgot Password"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Logged-in Views</h3>
|
||||
{{> button key="liv" value="accountButtons" label="Account Buttons"}}
|
||||
{{> button key="liv" value="changePassword" label="Change Password"}}
|
||||
{{> button key="liv" value="messageOnly" label="Message Only"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Other Modals</h3>
|
||||
{{> button key="modals" value="resetPassword" label="Reset Password"}}
|
||||
{{> button key="modals" value="enrollAccount" label="Enroll Account"}}
|
||||
{{> button key="modals" value="justVerifiedEmail" label="Verified Email"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Logging-in Spinner</h3>
|
||||
{{> radio key="fakeLoggingIn" value="false" label="Off"}}
|
||||
{{> radio key="fakeLoggingIn" value="true" label="Pretend loggingIn=true"}}
|
||||
</div>
|
||||
<div class="group">
|
||||
<h3>Background Color</h3>
|
||||
{{> radio key="bgcolor" value="white" label="White"}}
|
||||
{{> radio key="bgcolor" value="black" label="Black"}}
|
||||
{{> radio key="bgcolor" value="red" label="Red"}}
|
||||
</div>
|
||||
</div>
|
||||
{{#with settings}}
|
||||
<div id="previewpane" class="{{settingsClass}}" style="background:{{bgcolor}}">
|
||||
<div id="preview-wrapper">
|
||||
{{#if match "positioning:inline"}}
|
||||
Here is a place to sign in, yay!
|
||||
{{/if}}
|
||||
{{> loginButtons align=dropdownAlign}}
|
||||
{{#if match "positioning:inline"}}
|
||||
Isn't that great?
|
||||
{{/if}}
|
||||
</div>
|
||||
<div id="pos-indicator"></div>
|
||||
{{#unless match "positioning:absolute"}}
|
||||
<div style="clear:both">
|
||||
A line that shouldn't move when logging in and logging out
|
||||
</div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{/with}}
|
||||
</template>
|
||||
@@ -1,221 +0,0 @@
|
||||
|
||||
Meteor.users.allow({ update: () => true });
|
||||
|
||||
const { ServiceConfiguration } = Package['service-configuration'];
|
||||
|
||||
Meteor.methods({
|
||||
'removeService': service => ServiceConfiguration.configurations.remove({ service }),
|
||||
})
|
||||
|
||||
if (Meteor.isClient) {
|
||||
|
||||
Accounts.STASH = { ...Accounts };
|
||||
Accounts.STASH.loggingIn = Meteor.loggingIn;
|
||||
|
||||
const handleSetting = (key, value) => {
|
||||
if (key === "numServices") {
|
||||
const registeredServices = Accounts.oauth.serviceNames();
|
||||
['facebook', 'github', 'google'].forEach((serv, i) => {
|
||||
if (i < value && !registeredServices.includes(serv)) {
|
||||
Accounts.oauth.registerService(serv);
|
||||
} else if (i >= value && registeredServices.includes(serv)) {
|
||||
Accounts.oauth.unregisterService(serv);
|
||||
}
|
||||
});
|
||||
} else if (key === "hasPasswords") {
|
||||
Package['accounts-password'] = value ? {} : null;
|
||||
const user = Meteor.user();
|
||||
if (user) {
|
||||
if (! value) {
|
||||
// make sure we have no username if "app" has no passwords
|
||||
Meteor.users.update(Meteor.userId(),
|
||||
{ $unset: { username: 1 }});
|
||||
} else {
|
||||
// make sure we have a username
|
||||
Meteor.users.update(Meteor.userId(),
|
||||
{ $set: { username: Random.id() }});
|
||||
}
|
||||
}
|
||||
} else if (key === "signupFields") {
|
||||
Accounts.ui._options.passwordSignupFields = value;
|
||||
} else if (key === "fakeLoggingIn") {
|
||||
Meteor.loggingIn = (value ? () => true :
|
||||
Accounts.STASH.loggingIn);
|
||||
}
|
||||
};
|
||||
|
||||
const settings = Session.get('settings');
|
||||
if (! settings) {
|
||||
Session.set('settings', {
|
||||
alignRight: false,
|
||||
positioning: "relative",
|
||||
numServices: 3,
|
||||
hasPasswords: true,
|
||||
signupFields: 'EMAIL_ONLY',
|
||||
fakeLoggingIn: false,
|
||||
bgcolor: 'white'
|
||||
});
|
||||
} else {
|
||||
Object.keys(settings).forEach(key => handleSetting(key, settings[key]));
|
||||
}
|
||||
|
||||
Template.page.helpers({
|
||||
settings: () => Session.get('settings'),
|
||||
settingsClass: () => {
|
||||
var settings = Session.get('settings');
|
||||
var classes = [];
|
||||
if (settings.positioning)
|
||||
classes.push('positioning-' + settings.positioning.toLowerCase());
|
||||
return classes.join(' ');
|
||||
},
|
||||
match: kv => {
|
||||
kv = keyValueFromId(kv);
|
||||
if (! kv)
|
||||
return false;
|
||||
|
||||
return Session.get('settings')[kv[0]] === kv[1];
|
||||
},
|
||||
dropdownAlign: function() {
|
||||
var settings = this;
|
||||
return settings.alignRight ? 'right' : 'left';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var keyValueFromId = function (id) {
|
||||
var match;
|
||||
if (id && (match = /^(.*?):(.*)$/.exec(id))) {
|
||||
var key = match[1];
|
||||
var value = castValue(match[2]);
|
||||
return [key, value];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const castValue = value => {
|
||||
if (value === "false")
|
||||
value = false;
|
||||
else if (value === "true")
|
||||
value = true;
|
||||
else if (/^[0-9]+$/.test(value))
|
||||
value = Number(value);
|
||||
return value;
|
||||
};
|
||||
|
||||
Template.radio.helpers({
|
||||
maybeChecked: function() {
|
||||
var curValue = Session.get('settings')[this.key];
|
||||
if (castValue(this.value) === curValue)
|
||||
return 'checked';
|
||||
return '';
|
||||
},
|
||||
});
|
||||
|
||||
const fakeLogin = callback => {
|
||||
Accounts.createUser(
|
||||
{username: Random.id(),
|
||||
password: "password",
|
||||
profile: { name: "Joe Schmoe" }},
|
||||
() => {
|
||||
var user = Meteor.user();
|
||||
if (! user)
|
||||
return;
|
||||
// delete our username if we are in a mode
|
||||
// where there aren't usernames/emails/passwords
|
||||
// (only third-party auth) so that there is no
|
||||
// "Change Password" button when signed in
|
||||
if (! Session.get('settings').hasPasswords)
|
||||
Meteor.users.update(Meteor.userId(),
|
||||
{ $unset: { username: 1 }});
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
const exitFlows = () => {
|
||||
Accounts._loginButtonsSession.set('inSignupFlow', false);
|
||||
Accounts._loginButtonsSession.set('inForgotPasswordFlow', false);
|
||||
Accounts._loginButtonsSession.set('inChangePasswordFlow', false);
|
||||
Accounts._loginButtonsSession.set('inMessageOnlyFlow', false);
|
||||
};
|
||||
|
||||
Template.page.events({
|
||||
'change #controlpane input[type=radio]': event => {
|
||||
const input = event.currentTarget;
|
||||
let keyValue;
|
||||
if (input && input.id && (keyValue = keyValueFromId(input.id))) {
|
||||
const key = keyValue[0];
|
||||
const value = keyValue[1];
|
||||
if (value === "false")
|
||||
value = false;
|
||||
else if (value === "true")
|
||||
value = true;
|
||||
const settings = Session.get('settings');
|
||||
settings[key] = value;
|
||||
Session.set('settings', settings);
|
||||
|
||||
handleSetting(key, value);
|
||||
}
|
||||
},
|
||||
'click #controlpane button': function (event) {
|
||||
const { ServiceConfiguration } = Package['service-configuration'];
|
||||
if (this.key === "fakeConfig") {
|
||||
const service = this.value;
|
||||
if (! ServiceConfiguration.configurations.findOne({ service }))
|
||||
ServiceConfiguration.configurations.insert(
|
||||
{ service, fake: true });
|
||||
} else if (this.key === "unconfig") {
|
||||
const service = this.value;
|
||||
Meteor.call('removeService', service);
|
||||
} else if (this.key === "messages") {
|
||||
if (this.value === "error") {
|
||||
Accounts._loginButtonsSession.errorMessage('An error occurred! Gee golly gosh.');
|
||||
} else if (this.value === "info") {
|
||||
Accounts._loginButtonsSession.infoMessage('Here is some information that is crucial.');
|
||||
} else if (this.value === "clear") {
|
||||
Accounts._loginButtonsSession.resetMessages();
|
||||
}
|
||||
} else if (this.key === "sign") {
|
||||
if (this.value === 'in') {
|
||||
// create a random new user
|
||||
fakeLogin(function () {
|
||||
Accounts._loginButtonsSession.closeDropdown();
|
||||
});
|
||||
} else if (this.value === 'out') {
|
||||
Meteor.logout();
|
||||
}
|
||||
} else if (this.key === "showConfig") {
|
||||
Accounts._loginButtonsSession.configureService(this.value);
|
||||
} else if (this.key === "lov") {
|
||||
exitFlows();
|
||||
Accounts._loginButtonsSession.set("dropdownVisible", true);
|
||||
if (Meteor.userId())
|
||||
Meteor.logout();
|
||||
if (this.value === "createAccount")
|
||||
Accounts._loginButtonsSession.set("inSignupFlow", true);
|
||||
else if (this.value === "forgotPassword")
|
||||
Accounts._loginButtonsSession.set("inForgotPasswordFlow", true);
|
||||
} else if (this.key === "liv") {
|
||||
exitFlows();
|
||||
Accounts._loginButtonsSession.set("dropdownVisible", true);
|
||||
if (! Meteor.userId())
|
||||
fakeLogin(() => {});
|
||||
if (this.value === "changePassword")
|
||||
Accounts._loginButtonsSession.set("inChangePasswordFlow", true);
|
||||
else if (this.value === "messageOnly")
|
||||
Accounts._loginButtonsSession.set("inMessageOnlyFlow", true);
|
||||
} else if (this.key === "modals") {
|
||||
const { value } = this;
|
||||
[
|
||||
'resetPasswordToken',
|
||||
'enrollAccountToken',
|
||||
'justVerifiedEmail'
|
||||
].forEach(k => {
|
||||
Accounts._loginButtonsSession.set(
|
||||
k, k.indexOf(value) >= 0 ? 'foo' : null
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
html, body { height: 100%; }
|
||||
|
||||
#controlpane {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 299px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
background: #eee;
|
||||
border-right: 1px solid #999;
|
||||
|
||||
overflow: auto;
|
||||
|
||||
h3 {
|
||||
border-top: 1px solid #999;
|
||||
font-size: 85%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.group {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
input[type=radio] {
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
label {
|
||||
padding-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
#previewpane {
|
||||
position: absolute;
|
||||
left: 300px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
#preview-wrapper {
|
||||
margin: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.radio {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.positioning-floatright {
|
||||
#login-buttons {
|
||||
float: right;
|
||||
margin-right: 180px;
|
||||
}
|
||||
|
||||
#pos-indicator {
|
||||
display: block;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 200px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.positioning-relative {
|
||||
#login-buttons {
|
||||
position: relative;
|
||||
left: 150px;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
#pos-indicator {
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 170px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.positioning-absolute {
|
||||
#login-buttons {
|
||||
position: absolute;
|
||||
left: 170px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
#pos-indicator {
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 170px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
#pos-indicator {
|
||||
position: absolute;
|
||||
background: #eec;
|
||||
display: none;
|
||||
}
|
||||
|
||||
a { color: blue; }
|
||||
|
||||
button { padding: 4px;
|
||||
margin-bottom: 4px; // for when buttons wrap
|
||||
}
|
||||
682
examples/unfinished/accounts-ui-viewer/package-lock.json
generated
682
examples/unfinished/accounts-ui-viewer/package-lock.json
generated
@@ -1,682 +0,0 @@
|
||||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.0.0-beta.38",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.38.tgz",
|
||||
"integrity": "sha512-ZvPtlcvH2ZRzr1U5pkmCE7U3RIun3Nf29XHem47aScmJgMuL06ulkp+4oPBee3QrUVFErDjwNWtC67BzNuxLVw==",
|
||||
"requires": {
|
||||
"core-js": "2.5.3",
|
||||
"regenerator-runtime": "0.11.1"
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
|
||||
"integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4="
|
||||
},
|
||||
"meteor-node-stubs": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.2.tgz",
|
||||
"integrity": "sha512-l93SS/HutbqBRJODO2m7hup8cYI2acF5bB39+ZvP2BX8HMmCSCXeFH7v0sr4hD7zrVvHQA5UqS0pcDYKn0VM6g==",
|
||||
"requires": {
|
||||
"assert": "1.4.1",
|
||||
"browserify-zlib": "0.1.4",
|
||||
"buffer": "4.9.1",
|
||||
"console-browserify": "1.1.0",
|
||||
"constants-browserify": "1.0.0",
|
||||
"crypto-browserify": "3.11.1",
|
||||
"domain-browser": "1.1.7",
|
||||
"events": "1.1.1",
|
||||
"http-browserify": "1.7.0",
|
||||
"https-browserify": "0.0.1",
|
||||
"os-browserify": "0.2.1",
|
||||
"path-browserify": "0.0.0",
|
||||
"process": "0.11.10",
|
||||
"punycode": "1.4.1",
|
||||
"querystring-es3": "0.2.1",
|
||||
"readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
|
||||
"stream-browserify": "2.0.1",
|
||||
"string_decoder": "1.0.3",
|
||||
"timers-browserify": "1.4.2",
|
||||
"tty-browserify": "0.0.0",
|
||||
"url": "0.11.0",
|
||||
"util": "0.10.3",
|
||||
"vm-browserify": "0.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"Base64": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
|
||||
"integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
|
||||
},
|
||||
"asn1.js": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz",
|
||||
"integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"inherits": "2.0.1",
|
||||
"minimalistic-assert": "1.0.0"
|
||||
}
|
||||
},
|
||||
"assert": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
|
||||
"integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
|
||||
"requires": {
|
||||
"util": "0.10.3"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
|
||||
"integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
|
||||
},
|
||||
"bn.js": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
|
||||
"integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
||||
"requires": {
|
||||
"balanced-match": "1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"brorand": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
|
||||
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.0.tgz",
|
||||
"integrity": "sha512-W2bIMLYoZ9oow7TyePpMJk9l9LY7O3R61a/68bVCDOtnJynnwe3ZeW2IzzSkrQnPKNdJrxVDn3ALZNisSBwb7g==",
|
||||
"requires": {
|
||||
"buffer-xor": "1.0.3",
|
||||
"cipher-base": "1.0.4",
|
||||
"create-hash": "1.1.3",
|
||||
"evp_bytestokey": "1.0.3",
|
||||
"inherits": "2.0.1",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"browserify-cipher": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
|
||||
"integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
|
||||
"requires": {
|
||||
"browserify-aes": "1.1.0",
|
||||
"browserify-des": "1.0.0",
|
||||
"evp_bytestokey": "1.0.3"
|
||||
}
|
||||
},
|
||||
"browserify-des": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
|
||||
"integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
|
||||
"requires": {
|
||||
"cipher-base": "1.0.4",
|
||||
"des.js": "1.0.0",
|
||||
"inherits": "2.0.1"
|
||||
}
|
||||
},
|
||||
"browserify-rsa": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"randombytes": "2.0.5"
|
||||
}
|
||||
},
|
||||
"browserify-sign": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
|
||||
"integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"browserify-rsa": "4.0.1",
|
||||
"create-hash": "1.1.3",
|
||||
"create-hmac": "1.1.6",
|
||||
"elliptic": "6.4.0",
|
||||
"inherits": "2.0.1",
|
||||
"parse-asn1": "5.1.0"
|
||||
}
|
||||
},
|
||||
"browserify-zlib": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
|
||||
"integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
|
||||
"requires": {
|
||||
"pako": "0.2.9"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
||||
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
|
||||
"requires": {
|
||||
"base64-js": "1.2.1",
|
||||
"ieee754": "1.1.8",
|
||||
"isarray": "1.0.0"
|
||||
}
|
||||
},
|
||||
"buffer-xor": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
|
||||
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
|
||||
},
|
||||
"cipher-base": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
|
||||
"requires": {
|
||||
"inherits": "2.0.1",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"console-browserify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
|
||||
"integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
|
||||
"requires": {
|
||||
"date-now": "0.1.4"
|
||||
}
|
||||
},
|
||||
"constants-browserify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
|
||||
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
|
||||
"integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"elliptic": "6.4.0"
|
||||
}
|
||||
},
|
||||
"create-hash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
|
||||
"integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
|
||||
"requires": {
|
||||
"cipher-base": "1.0.4",
|
||||
"inherits": "2.0.1",
|
||||
"ripemd160": "2.0.1",
|
||||
"sha.js": "2.4.9"
|
||||
}
|
||||
},
|
||||
"create-hmac": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
|
||||
"integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
|
||||
"requires": {
|
||||
"cipher-base": "1.0.4",
|
||||
"create-hash": "1.1.3",
|
||||
"inherits": "2.0.1",
|
||||
"ripemd160": "2.0.1",
|
||||
"safe-buffer": "5.1.1",
|
||||
"sha.js": "2.4.9"
|
||||
}
|
||||
},
|
||||
"crypto-browserify": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz",
|
||||
"integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==",
|
||||
"requires": {
|
||||
"browserify-cipher": "1.0.0",
|
||||
"browserify-sign": "4.0.4",
|
||||
"create-ecdh": "4.0.0",
|
||||
"create-hash": "1.1.3",
|
||||
"create-hmac": "1.1.6",
|
||||
"diffie-hellman": "5.0.2",
|
||||
"inherits": "2.0.1",
|
||||
"pbkdf2": "3.0.14",
|
||||
"public-encrypt": "4.0.0",
|
||||
"randombytes": "2.0.5"
|
||||
}
|
||||
},
|
||||
"date-now": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
||||
"integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
|
||||
},
|
||||
"des.js": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
|
||||
"integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
|
||||
"requires": {
|
||||
"inherits": "2.0.1",
|
||||
"minimalistic-assert": "1.0.0"
|
||||
}
|
||||
},
|
||||
"diffie-hellman": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
|
||||
"integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"miller-rabin": "4.0.1",
|
||||
"randombytes": "2.0.5"
|
||||
}
|
||||
},
|
||||
"domain-browser": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
|
||||
"integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw="
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||||
"integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"brorand": "1.1.0",
|
||||
"hash.js": "1.1.3",
|
||||
"hmac-drbg": "1.0.1",
|
||||
"inherits": "2.0.1",
|
||||
"minimalistic-assert": "1.0.0",
|
||||
"minimalistic-crypto-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
|
||||
},
|
||||
"evp_bytestokey": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||
"integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
|
||||
"requires": {
|
||||
"md5.js": "1.3.4",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "1.0.0",
|
||||
"inflight": "1.0.6",
|
||||
"inherits": "2.0.1",
|
||||
"minimatch": "3.0.4",
|
||||
"once": "1.4.0",
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
},
|
||||
"hash-base": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
|
||||
"integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
|
||||
"requires": {
|
||||
"inherits": "2.0.1"
|
||||
}
|
||||
},
|
||||
"hash.js": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
|
||||
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
|
||||
"requires": {
|
||||
"inherits": "2.0.3",
|
||||
"minimalistic-assert": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
"integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
|
||||
"requires": {
|
||||
"hash.js": "1.1.3",
|
||||
"minimalistic-assert": "1.0.0",
|
||||
"minimalistic-crypto-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"http-browserify": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
|
||||
"integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
|
||||
"requires": {
|
||||
"Base64": "0.2.1",
|
||||
"inherits": "2.0.1"
|
||||
}
|
||||
},
|
||||
"https-browserify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz",
|
||||
"integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI="
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
|
||||
"integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
|
||||
},
|
||||
"indexof": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
||||
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "1.4.0",
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"md5.js": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
|
||||
"integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
|
||||
"requires": {
|
||||
"hash-base": "3.0.4",
|
||||
"inherits": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"hash-base": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
|
||||
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
|
||||
"requires": {
|
||||
"inherits": "2.0.1",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"miller-rabin": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
|
||||
"integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"brorand": "1.1.0"
|
||||
}
|
||||
},
|
||||
"minimalistic-assert": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
|
||||
"integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
|
||||
},
|
||||
"minimalistic-crypto-utils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
|
||||
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "1.1.8"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"os-browserify": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz",
|
||||
"integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8="
|
||||
},
|
||||
"pako": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
|
||||
},
|
||||
"parse-asn1": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
|
||||
"integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
|
||||
"requires": {
|
||||
"asn1.js": "4.9.1",
|
||||
"browserify-aes": "1.1.0",
|
||||
"create-hash": "1.1.3",
|
||||
"evp_bytestokey": "1.0.3",
|
||||
"pbkdf2": "3.0.14"
|
||||
}
|
||||
},
|
||||
"path-browserify": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
|
||||
"integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"pbkdf2": {
|
||||
"version": "3.0.14",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
|
||||
"integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
|
||||
"requires": {
|
||||
"create-hash": "1.1.3",
|
||||
"create-hmac": "1.1.6",
|
||||
"ripemd160": "2.0.1",
|
||||
"safe-buffer": "5.1.1",
|
||||
"sha.js": "2.4.9"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
|
||||
"integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"browserify-rsa": "4.0.1",
|
||||
"create-hash": "1.1.3",
|
||||
"parse-asn1": "5.1.0",
|
||||
"randombytes": "2.0.5"
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
||||
},
|
||||
"querystring-es3": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
||||
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
|
||||
"integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
|
||||
"requires": {
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "1.0.7",
|
||||
"safe-buffer": "5.1.1",
|
||||
"string_decoder": "1.0.3",
|
||||
"util-deprecate": "1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
|
||||
"requires": {
|
||||
"glob": "7.1.2"
|
||||
}
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
|
||||
"integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
|
||||
"requires": {
|
||||
"hash-base": "2.0.2",
|
||||
"inherits": "2.0.1"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.9",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
|
||||
"integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
|
||||
"requires": {
|
||||
"inherits": "2.0.1",
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"stream-browserify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
|
||||
"integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
|
||||
"requires": {
|
||||
"inherits": "2.0.1",
|
||||
"readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"timers-browserify": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
|
||||
"integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
|
||||
"requires": {
|
||||
"process": "0.11.10"
|
||||
}
|
||||
},
|
||||
"tty-browserify": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
|
||||
},
|
||||
"url": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
||||
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
|
||||
"requires": {
|
||||
"punycode": "1.3.2",
|
||||
"querystring": "0.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
||||
}
|
||||
}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.10.3",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
||||
"requires": {
|
||||
"inherits": "2.0.1"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"vm-browserify": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
|
||||
"integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
|
||||
"requires": {
|
||||
"indexof": "0.0.1"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "accounts-ui-viewer",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "meteor run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0-beta.38",
|
||||
"meteor-node-stubs": "^0.3.2"
|
||||
}
|
||||
}
|
||||
1
examples/unfinished/atoms/.meteor/.gitignore
vendored
1
examples/unfinished/atoms/.meteor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,9 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
standard-app-packages
|
||||
autopublish
|
||||
insecure
|
||||
underscore
|
||||
@@ -1 +0,0 @@
|
||||
none
|
||||
@@ -1,12 +0,0 @@
|
||||
g[class=atom] circle {
|
||||
stroke: black;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
g[class=atom] text {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 24px;
|
||||
fill: black;
|
||||
font-weight: bold;
|
||||
text-anchor: middle;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<head>
|
||||
<title>Atoms</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="atoms">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500">
|
||||
{{#atom x=100 y=100 color="#ffff00"}}O{{/atom}}
|
||||
{{> hydrogen x=150 y=100}}
|
||||
{{#giantatom x=250 y=100 color="#ff9999"}}My{{/giantatom}}
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<template name="atom">
|
||||
<g class="atom">
|
||||
<circle style="fill: {{#if color}}{{color}}{{else}}white{{/if}}" cx={{x}} cy={{y}} r={{#if r}}{{r}}{{else}}20{{/if}} />
|
||||
<text x={{x}} y={{textY}}>{{> UI.contentBlock}}</text>
|
||||
</g>
|
||||
</template>
|
||||
|
||||
<template name="hydrogen">
|
||||
{{#atom x=x y=y r=r color="#00ffff"}}H{{/atom}}
|
||||
</template>
|
||||
|
||||
<template name="giantatom">
|
||||
{{#atom x=x y=y r=50 color=color}}{{> UI.contentBlock}}{{/atom}}
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
if (Meteor.isClient) {
|
||||
Template.atom.textY = function () {
|
||||
return this.y + 8;
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
local
|
||||
@@ -1,9 +0,0 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
underscore
|
||||
jquery
|
||||
jquery-layout
|
||||
standard-app-packages
|
||||
@@ -1 +0,0 @@
|
||||
0.6.0
|
||||
@@ -1,26 +0,0 @@
|
||||
#room-list .room.selected {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.room .name {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.room .delete {
|
||||
float: right;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.room:hover .delete {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.add-room {
|
||||
margin-top: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.add-room:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<body>
|
||||
|
||||
<div class="ui-layout-center" id="chat-view">
|
||||
{{> center_pane }}
|
||||
</div>
|
||||
<div class="ui-layout-east">East</div>
|
||||
<div class="ui-layout-west">
|
||||
{{> room_list}}
|
||||
{{> add_room}}
|
||||
</div>
|
||||
<div class="ui-layout-north">Azrael</div>
|
||||
|
||||
</body>
|
||||
|
||||
<template name="room_list">
|
||||
<div id="room-list">
|
||||
{{#each rooms}}
|
||||
{{> room}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="add_room">
|
||||
<div class="add-room">
|
||||
Create new room
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="room">
|
||||
<div class="room {{maybe_selected}}">
|
||||
{{#if editing}}
|
||||
<input id="room_name_input" value="{{name}}">
|
||||
{{else}}
|
||||
<div class="name">{{name}}</div>
|
||||
<div class="delete">(x)</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="center_pane">
|
||||
<div id="center-pane">
|
||||
{{#if any_room_selected}}
|
||||
<div id="chat">
|
||||
{{#each messages}}
|
||||
{{> chat_message}}
|
||||
{{else}}
|
||||
No chat yet!
|
||||
{{/each}}
|
||||
</div>
|
||||
<input id="chat-entry">
|
||||
{{else}}
|
||||
No room selected
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="chat_message">
|
||||
<div>
|
||||
{{username}}: {{message}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,128 +0,0 @@
|
||||
Meteor.subscribe('rooms');
|
||||
|
||||
Session.set('current_room', null);
|
||||
Session.set('editing_room_name', false);
|
||||
|
||||
Deps.autorun(function () {
|
||||
var room_id = Session.get('current_room');
|
||||
if (room_id) Meteor.subscribe('room-detail', room_id);
|
||||
});
|
||||
|
||||
// XXX would be nice to eliminate this function and have people just
|
||||
// call Session.set("current_room", foo) directly instead
|
||||
var selectRoom = function (room_id) {
|
||||
// XXX pushstate
|
||||
var room = Rooms.find(room_id);
|
||||
Session.set('current_room', room_id);
|
||||
};
|
||||
|
||||
Meteor.startup(function () {
|
||||
$('body').layout({applyDefaultStyles: true})
|
||||
});
|
||||
|
||||
Template.room_list.rooms = function () {
|
||||
// XXX it would be nice if this were find instead of findLive (ie,
|
||||
// if they were unified in some sane way)
|
||||
return Rooms.findLive({}, {sort: {name: 1}});
|
||||
};
|
||||
|
||||
Template.add_room.events = {
|
||||
'click': function () {
|
||||
// XXX should put up dialog to get name
|
||||
// XXX should support automatically set created/updated timestamps
|
||||
var room_id = Rooms.insert({name: "New room",
|
||||
// XXX horrid syntax
|
||||
created: (new Date()).getTime()});
|
||||
selectRoom(room_id);
|
||||
// XXX XXX XXX this fails to work -- it leaves edit mode after
|
||||
// 1RTT. what happens is, the server echos the insert back to us,
|
||||
// and that is currently wired up to trigger a changed event on
|
||||
// the findlive, which redraws the element, which triggers blur,
|
||||
// which causes us to set editing_room_name to false.
|
||||
//
|
||||
// one option is to have the rendering function (maybe in a
|
||||
// post-render routine?) decide if it currently wants
|
||||
// focus. (should that be within the recomputation envelope, I
|
||||
// wonder?)
|
||||
//
|
||||
// another is to suppress blur on rerender. probably the only
|
||||
// principled way to do this is to narrow the scope of the
|
||||
// rerender to not include the <input>.
|
||||
//
|
||||
// [No idea if the comment above is still current]
|
||||
Session.set('editing_room_name', true);
|
||||
Deps.flush();
|
||||
$('#room_name_input').focus();
|
||||
}
|
||||
};
|
||||
|
||||
Template.room.events = {
|
||||
'mousedown': function (evt) {
|
||||
selectRoom(this._id);
|
||||
},
|
||||
'dblclick': function (evt) {
|
||||
Session.set('editing_room_name', true);
|
||||
// XXX XXX doesn't generalize.. the element might very reasonably
|
||||
// not have a unique id. may need a different strategy..
|
||||
Deps.flush();
|
||||
$('#room_name_input').focus();
|
||||
},
|
||||
'blur input': function (evt) {
|
||||
Session.set('editing_room_name', false);
|
||||
},
|
||||
'keypress input': function (evt) {
|
||||
// XXX should really have a binding/validator-based pattern
|
||||
// XXX check to see this pattern works if you are saving
|
||||
// continuously (on every keystroke)
|
||||
var value = $(evt.target).val();
|
||||
if (evt.which === 13 && value.length)
|
||||
Rooms.update(this._id, {$set: {name: value}});
|
||||
if (evt.which === 13 || evt.which === 27)
|
||||
Session.set('editing_room_name', false);
|
||||
},
|
||||
// If you make this event be click (rather than mousedown), then
|
||||
// delete doesn't work if the room isn't already selected. what
|
||||
// happens is, the mousedown triggers the selection, which redraws
|
||||
// the room, meaning that the elements are replaced out from under
|
||||
// the event, and the click event is lost.. bleh. needs
|
||||
// reconsideration.
|
||||
'mousedown .delete': function (evt) {
|
||||
Rooms.remove('rooms', this._id);
|
||||
Session.set('current_room', null);
|
||||
},
|
||||
};
|
||||
|
||||
Template.room.editing = function (options) {
|
||||
// Check current_room first, before editing_room_name, to minimize
|
||||
// number of redraws
|
||||
return (Session.equals('current_room', this._id) &&
|
||||
Session.equals('editing_room_name', true));
|
||||
};
|
||||
|
||||
Template.room.maybe_selected = function () {
|
||||
return Session.equals('current_room', this._id) ? "selected" : "";
|
||||
};
|
||||
|
||||
Template.center_pane.messages = function () {
|
||||
return Chat.findLive({room: Session.get("current_room")},
|
||||
{sort: {created: 1}});
|
||||
};
|
||||
|
||||
Template.center_pane.any_room_selected = function () {
|
||||
return !Session.equals('current_room', null);
|
||||
};
|
||||
|
||||
Template.center_pane.events = {
|
||||
'keydown #chat-entry': function (evt) {
|
||||
if (evt.which === 13) {
|
||||
var room_id = Session.get('current_room');
|
||||
if (!room_id)
|
||||
return;
|
||||
|
||||
Chat.insert({room: room_id, message: $(evt.target).val(),
|
||||
username: "someone",
|
||||
created: (new Date()).getTime()});
|
||||
$(evt.target).val('');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
// XXX it is actually very dangerous to store times as Number. use
|
||||
// Date type once it's implemented in minimongo
|
||||
Rooms = new Mongo.Collection("rooms");
|
||||
//Rooms.schema({name: String, created: Number});
|
||||
|
||||
Chat = new Mongo.Collection("chat");
|
||||
/*
|
||||
Chat.schema({room: String, message: String,
|
||||
username: String, created: Number});
|
||||
*/
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Meteor.publish('rooms', function () {
|
||||
return Rooms.find();
|
||||
});
|
||||
|
||||
// XXX should limit to just a certain amount of recent chat ..
|
||||
Meteor.publish('room-detail', function (room) {
|
||||
return Chat.find({room: room});
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user