diff --git a/.dockerignore b/.dockerignore index aaca40b6a51557fb782f4c4b24e46d97de773c32..fb00b3c09226ce7db6d952f2933f56ced7c53450 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,12 +1,15 @@ -.dockerignore +# Common +*/.git Dockerfile -db.sqlite3 -__pycache__ + +# Django + +*/db.sqlite3 +*/__pycache__* *.pyc *.pyo *.pyd -.Python -env +*/env* pip-log.txt pip-delete-this-directory.txt .tox @@ -16,4 +19,8 @@ pip-delete-this-directory.txt coverage.xml *,cover *.log -.git + + +# node +*/node_modules +*/npm-debug.log diff --git a/.gitignore b/.gitignore index 01d0435e3c627390d39f2a4f158ae513f293e188..04005159a65f154e523f2f6be8ee5e9e6c839f25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1,6 @@ -# If you need to exclude files such as those generated by an IDE, use -# $GIT_DIR/info/exclude or the core.excludesFile configuration variable as -# described in https://git-scm.com/docs/gitignore - -# python specific -*.egg-info -*.pot -*.py[co] -.tox/ -__pycache__ -MANIFEST -.coverage -cache/ - -# Django specific -dist/ -docs/_build/ -docs/locale/ -node_modules/ -tests/coverage_html/ -tests/.coverage -build/ -static/ -tests/report/ -*.sqlite3 -env/ -static/ - -# project specific -env-grady/ -env/ -scripts/ -*.csv -*.json -.importer* - # operation system .DS_Store -# sublime specific +# ide specific *.sublime-* - -# yarn stuff -node_modules +.idea/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43e0b09d954d9a1df6ac43029d861a8ffc1b9df8..0ec2cf3495f0e6cb2ed615ded22c234bd3140fab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,3 @@ - stages: - build - test @@ -7,7 +6,8 @@ stages: variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME -build: +# ============================= Building section ============================= # +build_backend: image: docker:latest stage: build script: @@ -15,25 +15,50 @@ build: - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG - -.test_template: &test_definition +# ============================== Testing section ============================= # +# ----------------------------- Backend subsection --------------------------- # +.test_template_backend: &test_definition_backend stage: test image: $IMAGE_TAG + before_script: + - cd backend/ test_coverage: - <<: *test_definition + <<: *test_definition_backend services: - postgres:9.5 script: - coverage run manage.py test --noinput - coverage report --skip-covered + artifacts: + paths: + - .coverage/ test_pylint: - <<: *test_definition + <<: *test_definition_backend script: - pylint core || exit 0 +test_prospector: + <<: *test_definition_backend + script: + - prospector --uses django || exit 0 + +# ----------------------------- Frontend subsection -------------------------- # +.test_template_frontend: &test_definition_frontend + image: node:carbon + stage: test + before_script: + - cd frontend/ + +test_frontend: + <<: *test_definition_frontend + script: + - yarn install + - yarn test --single-run + allow_failure: true +# ============================== Staging section ============================= # .staging_template: &staging_definition stage: staging image: docker:latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b2f4c009357ff738a45f0edd40bdd00f00fb1899 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +repos: +- repo: local + hooks: + - id: prospector + name: prospector + entry: ./pre-commit-scripts/prospector.sh + language: script + types: [python] diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index ba51efd0753f4db9647723dd2af24b436b0ffba5..0000000000000000000000000000000000000000 --- a/.pylintrc +++ /dev/null @@ -1,140 +0,0 @@ -[MASTER] - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS, migrations, static, env, docs, manage.py - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=2 - -# Pickle collected data for later comparisons. -persistent=yes - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - locally-enabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating - -[REPORTS] - -# Tells whether to display a full report or only the messages -reports=yes - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=100 diff --git a/Dockerfile b/Dockerfile index d56c36bcbe33d64601584bade182c6eb8fdce1e3..acec75a13f543e9177e51379f3f534c70ba76d44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,16 @@ # Build Python files FROM python:3.6 as python -COPY requirements.txt . +COPY backend/requirements.txt . RUN pip install -r requirements.txt RUN curl https://gitlab.gwdg.de/snippets/51/raw --output words -# Retrieve noes files -FROM node:latest as node -COPY package.json . -RUN yarn +FROM node:carbon as node + +WORKDIR /app/ +COPY frontend/ . + +RUN npm install +RUN npm run build # Now fetch other files and build on small image FROM python:3.6-alpine @@ -22,14 +25,11 @@ RUN apk update \ && apk del build-deps RUN mkdir -p /usr/share/dict -RUN mkdir /code -WORKDIR /code +WORKDIR /code/backend COPY . /code COPY --from=python /root/.cache /root/.cache COPY --from=python /words /usr/share/dict/words -# TODO this won't be necessarry anymore once merged with development -# since the node_modules are served form the Project Root there -COPY --from=node /node_modules core/static/node_modules +COPY --from=node /app/dist /code/backend/static RUN pip install -r requirements.txt && rm -rf /root/.cache diff --git a/Makefile b/Makefile index 63dd67bead6947b1df68d7c214d6de4967842145..4b670d2d353e708df4dbc2cea23f966761ce9111 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,14 @@ DB_NAME = postgres .PHONY: collectstatic run install migrations-check isort isort-check collectstatic: # used only in production - ./manage.py collectstatic --ignore node_modules + ./backend/manage.py collectstatic --ignore node_modules ./manage.py compress --force run: - python manage.py runserver 0.0.0.0:8000 + python backend/manage.py runserver 0.0.0.0:8000 migrations-check: - python manage.py makemigrations --check --dry-run + python backend/manage.py makemigrations --check --dry-run isort: isort -rc $(APP_LIST) @@ -20,21 +20,22 @@ isort-check: isort -c -rc $(APP_LIST) loaddata: - ./manage.py loaddata core/fixtures/testdata-groups.json + ./backend/manage.py loaddata core/fixtures/testdata-groups.json loadexamples: - ./manage.py loaddata core/fixtures/testdata-user.json - ./manage.py loaddata core/fixtures/testdata-core.json + ./backend/manage.py loaddata core/fixtures/testdata-user.json + ./backend/manage.py loaddata core/fixtures/testdata-core.json install: - pip install -r requirements.txt - yarn install --modules-folder core/static/node_modules + pip install -r backend/requirements.txt + yarn --cwd frontend/ + yarn --cwd backend/ test: - python manage.py run test + python backend/manage.py run test coverage: - coverage run manage.py test + coverage run backend/manage.py test coverage report docker-db-create: @@ -44,4 +45,4 @@ docker-db-start: docker start $(DB_NAME) docker-db-stop: - docker start $(DB_NAME) + docker stop $(DB_NAME) diff --git a/README.md b/README.md index c1528aa1c1972f1f56509804a186287c658335f7..dc345b7c440baaccfc7a6fedd7aef604f25a4dde 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,9 @@ To set up a new instance perform the following steps: 3. Install dependencies: - pip install -r requirements.txt - yarn install --modules-folder core/static/node_modules + pip install -r backend/requirements.txt + yarn --cwd frontend/ + yarn --cwd backend/ or alternatively with the make task: @@ -86,8 +87,7 @@ To set up a new instance perform the following steps: 6. To import some test data in order to see how the application might look like run: - - make loadexamples + make loadexamples 7. Everything is set. You can start the development server with: diff --git a/.coveragerc b/backend/.coveragerc similarity index 100% rename from .coveragerc rename to backend/.coveragerc diff --git a/.editorconfig b/backend/.editorconfig similarity index 100% rename from .editorconfig rename to backend/.editorconfig diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..438bae1f35383978b491783079cc5ab16c0546a6 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,27 @@ +# python specific +*.egg-info +*.pot +*.py[co] +.tox/ +__pycache__ +MANIFEST +.coverage +cache/ + +# Django specific +dist/ +docs/_build/ +docs/locale/ +tests/coverage_html/ +tests/.coverage +build/ +tests/report/ +*.sqlite3 +static/ + +# project specific +env-grady/ +env/ +scripts/ +*.csv +.importer* diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..64d359b2954d6172665aec7772875bbe9e4e9b98 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,42 @@ +APP_LIST ?= core grady util +DB_NAME = postgres + +.PHONY: collectstatic run install migrations-check isort isort-check + +collectstatic: # used only in production + python manage.py collectstatic --ignore node_modules + python manage.py compress --force + +run: + python manage.py runserver 0.0.0.0:8000 + +migrations-check: + python manage.py makemigrations --check --dry-run + +isort: + isort -rc $(APP_LIST) + +isort-check: + isort -c -rc $(APP_LIST) + +loaddata: + python manage.py loaddata core/fixtures/testdata-groups.json + +loadexamples: + python manage.py loaddata core/fixtures/testdata-user.json + python manage.py loaddata core/fixtures/testdata-core.json + +install: + pip install -r requirements.txt + yarn + +test: + python manage.py test + +coverage: + coverage run manage.py test + coverage report + +db: + docker run --rm --name $(DB_NAME) -p 5432:5432 postgres:9.5 + diff --git a/core/__init__.py b/backend/core/__init__.py similarity index 100% rename from core/__init__.py rename to backend/core/__init__.py diff --git a/backend/core/admin.py b/backend/core/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..a2e9f295ca1e3cb3e5c3afd5fef9ec0cc66a6443 --- /dev/null +++ b/backend/core/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin +from django.contrib.auth.models import Group + +from core.models import (ExamType, Feedback, Reviewer, Student, Submission, + SubmissionType, Test, Tutor, UserAccount) + +# Stuff we needwant +admin.site.register(UserAccount) +admin.site.register(SubmissionType) +admin.site.register(Feedback) +admin.site.register(Test) +admin.site.register(ExamType) +admin.site.register(Submission) +admin.site.register(Reviewer) +admin.site.register(Student) +admin.site.register(Tutor) + +# ... and stuff we don't needwant +admin.site.unregister(Group) diff --git a/core/apps.py b/backend/core/apps.py similarity index 100% rename from core/apps.py rename to backend/core/apps.py diff --git a/core/grady_speak.py b/backend/core/grady_speak.py similarity index 100% rename from core/grady_speak.py rename to backend/core/grady_speak.py diff --git a/backend/core/migrations/0001_initial.py b/backend/core/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..7fd6cdada7a80ed66d0adb09f55bb01c58a93272 --- /dev/null +++ b/backend/core/migrations/0001_initial.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.7 on 2017-11-04 19:10 +from __future__ import unicode_literals + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + +import core.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='UserAccount', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=150, unique=True)), + ('fullname', models.CharField(blank=True, max_length=70, verbose_name='full name')), + ('is_staff', models.BooleanField(default=False, verbose_name='staff status')), + ('is_admin', models.BooleanField(default=False)), + ('is_superuser', models.BooleanField(default=False)), + ('is_active', models.BooleanField(default=True, verbose_name='active')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ExamType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('module_reference', models.CharField(max_length=50, unique=True)), + ('total_score', models.PositiveIntegerField()), + ('pass_score', models.PositiveIntegerField()), + ('pass_only', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'ExamType', + 'verbose_name_plural': 'ExamTypes', + }, + ), + migrations.CreateModel( + name='Feedback', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('score', models.PositiveIntegerField(default=0)), + ('created', models.DateTimeField(auto_now_add=True)), + ('modified', models.DateTimeField(auto_now=True)), + ('status', models.IntegerField(choices=[(0, 'editable'), (1, 'request reassignment'), (2, 'request review'), (3, 'accepted')], default=0)), + ('origin', models.IntegerField(choices=[(0, 'was empty'), (1, 'passed unittests'), (2, 'did not compile'), (3, 'could not link'), (4, 'created by a human. yak!')], default=4)), + ], + options={ + 'verbose_name': 'Feedback', + 'verbose_name_plural': 'Feedback Set', + }, + ), + migrations.CreateModel( + name='Reviewer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='reviewer', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Student', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('has_logged_in', models.BooleanField(default=False)), + ('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='students', to='core.ExamType')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Student', + 'verbose_name_plural': 'Student Set', + }, + ), + migrations.CreateModel( + name='Submission', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('seen_by_student', models.BooleanField(default=False)), + ('text', models.TextField(blank=True)), + ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.Student')), + ], + options={ + 'verbose_name': 'Submission', + 'verbose_name_plural': 'Submission Set', + 'ordering': ('type__name',), + }, + ), + migrations.CreateModel( + name='SubmissionType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('full_score', models.PositiveIntegerField(default=0)), + ('description', models.TextField()), + ('solution', models.TextField()), + ], + options={ + 'verbose_name': 'SubmissionType', + 'verbose_name_plural': 'SubmissionType Set', + }, + ), + migrations.CreateModel( + name='Test', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('label', models.CharField(max_length=50)), + ('annotation', models.TextField()), + ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tests', to='core.Submission')), + ], + options={ + 'verbose_name': 'Test', + 'verbose_name_plural': 'Tests', + }, + ), + migrations.CreateModel( + name='Tutor', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='tutor', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='submission', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='submissions', to='core.SubmissionType'), + ), + migrations.AddField( + model_name='feedback', + name='of_reviewer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='reviewed_submissions', to='core.Reviewer'), + ), + migrations.AddField( + model_name='feedback', + name='of_submission', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'), + ), + migrations.AddField( + model_name='feedback', + name='of_tutor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='feedback_list', to='core.Tutor'), + ), + migrations.AlterUniqueTogether( + name='test', + unique_together=set([('submission', 'name')]), + ), + migrations.AlterUniqueTogether( + name='submission', + unique_together=set([('type', 'student')]), + ), + ] diff --git a/backend/core/migrations/0002_auto_20171110_1612.py b/backend/core/migrations/0002_auto_20171110_1612.py new file mode 100644 index 0000000000000000000000000000000000000000..d7eba8e70eb18ecc8e279c2dac007def36d06a48 --- /dev/null +++ b/backend/core/migrations/0002_auto_20171110_1612.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.7 on 2017-11-10 16:12 +from __future__ import unicode_literals + +import django.contrib.auth.models +import django.contrib.auth.validators +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ('core', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='useraccount', + options={'verbose_name': 'user', 'verbose_name_plural': 'users'}, + ), + migrations.AlterModelManagers( + name='useraccount', + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.AddField( + model_name='useraccount', + name='date_joined', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined'), + ), + migrations.AddField( + model_name='useraccount', + name='email', + field=models.EmailField(blank=True, max_length=254, verbose_name='email address'), + ), + migrations.AddField( + model_name='useraccount', + name='first_name', + field=models.CharField(blank=True, max_length=30, verbose_name='first name'), + ), + migrations.AddField( + model_name='useraccount', + name='groups', + field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'), + ), + migrations.AddField( + model_name='useraccount', + name='last_name', + field=models.CharField(blank=True, max_length=30, verbose_name='last name'), + ), + migrations.AddField( + model_name='useraccount', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), + ), + migrations.AlterField( + model_name='useraccount', + name='is_active', + field=models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active'), + ), + migrations.AlterField( + model_name='useraccount', + name='is_staff', + field=models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status'), + ), + migrations.AlterField( + model_name='useraccount', + name='is_superuser', + field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'), + ), + migrations.AlterField( + model_name='useraccount', + name='username', + field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'), + ), + ] diff --git a/backend/core/migrations/0003_student_matrikel_no.py b/backend/core/migrations/0003_student_matrikel_no.py new file mode 100644 index 0000000000000000000000000000000000000000..0beae351c7c15a7419470e4709ed9112a2d1f2f1 --- /dev/null +++ b/backend/core/migrations/0003_student_matrikel_no.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.7 on 2017-11-10 21:46 +from __future__ import unicode_literals + +import core.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_auto_20171110_1612'), + ] + + operations = [ + migrations.AddField( + model_name='student', + name='matrikel_no', + field=models.CharField(default=core.models.random_matrikel_no, max_length=8, unique=True), + ), + ] diff --git a/core/migrations/__init__.py b/backend/core/migrations/__init__.py similarity index 100% rename from core/migrations/__init__.py rename to backend/core/migrations/__init__.py diff --git a/core/models.py b/backend/core/models.py similarity index 82% rename from core/models.py rename to backend/core/models.py index 8e8f10a85a888177765f05bd7fb5864bce0022ed..1d1b23b19dbe7c77f4e9911035c85639578c74d3 100644 --- a/core/models.py +++ b/backend/core/models.py @@ -10,7 +10,8 @@ from collections import OrderedDict from random import randrange, sample from string import ascii_lowercase -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AbstractUser from django.db import models from django.db.models import Value as V from django.db.models import (BooleanField, Case, Count, F, IntegerField, Q, @@ -18,17 +19,6 @@ from django.db.models import (BooleanField, Case, Count, F, IntegerField, Q, from django.db.models.functions import Coalesce -def random_slug(slug_length: int=16) -> str: - """Used for all the slug fields in the application instead of relying on - the primary keys. They are not cryptographically secure since random is - used. - - Returns: - str: a random string of lowercase ACSII letter - """ - return ''.join(sample(ascii_lowercase, slug_length)) - - def random_matrikel_no() -> str: """Use as a default value for student's matriculation number. @@ -45,7 +35,7 @@ def get_annotated_tutor_list(): Returns: TYPE: the annotated QuerySet """ - return User.objects\ + return get_user_model().objects\ .filter(groups__name='Tutors')\ .annotate(Count('feedback_list'))\ .order_by('-feedback_list__count') @@ -78,9 +68,9 @@ class ExamType(models.Model): return self.module_reference module_reference = models.CharField(max_length=50, unique=True) - total_score = models.PositiveIntegerField() - pass_score = models.PositiveIntegerField() - pass_only = models.BooleanField(default=False) + total_score = models.PositiveIntegerField() + pass_score = models.PositiveIntegerField() + pass_only = models.BooleanField(default=False) class SubmissionType(models.Model): @@ -99,23 +89,19 @@ class SubmissionType(models.Model): name : CharField The original title of the exam. This is wildly used as an identifier by the preprocessing scripts. - slug : SlugField - unique TODO: is this needed? solution : TextField A sample solution or a correction guideline """ - name = models.CharField(max_length=50, unique=True) - full_score = models.PositiveIntegerField(default=0) + name = models.CharField(max_length=50, unique=True) + full_score = models.PositiveIntegerField(default=0) description = models.TextField() - solution = models.TextField() - slug = models.SlugField( - editable=False, unique=True, default=random_slug) + solution = models.TextField() def __str__(self) -> str: return self.name class Meta: - verbose_name = "SubmissionType" + verbose_name = "SubmissionType" verbose_name_plural = "SubmissionType Set" @classmethod @@ -133,7 +119,7 @@ class SubmissionType(models.Model): The annotated QuerySet as described above """ return cls.objects\ - .annotate( # to display only manual + .annotate( # to display only manual feedback_count=Count( Case( When( @@ -149,8 +135,40 @@ class SubmissionType(models.Model): ).order_by('name') +class UserAccount(AbstractUser): + """ + An abstract base class implementing a fully featured User model with + admin-compliant permissions. + + Username and password are required. Other fields are optional. + """ + + fullname = models.CharField('full name', max_length=70, blank=True) + is_admin = models.BooleanField(default=False) + + def get_associated_user(self): + """ Returns the user type that is associated with this user obj """ + return \ + (hasattr(self, 'student') and self.student) or \ + (hasattr(self, 'reviewer') and self.reviewer) or \ + (hasattr(self, 'tutor') and self.tutor) + + +class Tutor(models.Model): + user = models.OneToOneField( + get_user_model(), unique=True, + on_delete=models.CASCADE, related_name='tutor') + + +class Reviewer(models.Model): + user = models.OneToOneField( + get_user_model(), unique=True, + on_delete=models.CASCADE, related_name='reviewer') + + class Student(models.Model): - """The student model includes all information of a student, that we got + """ + The student model includes all information of a student, that we got from the E-Learning output, along with some useful classmethods that provide specially annotated QuerySets. @@ -166,27 +184,16 @@ class Student(models.Model): matrikel_no (CharField): The matriculation number of the student - - name (CharField): - The students full real name - - user (UserModel): - The django auth user that makes a student authenticates with. """ - has_logged_in = models.BooleanField(default=False) - name = models.CharField(max_length=50, default="__no_name__") - matrikel_no = models.CharField( + has_logged_in = models.BooleanField(default=False) + matrikel_no = models.CharField( unique=True, max_length=8, default=random_matrikel_no) - user = models.OneToOneField( - User, on_delete=models.CASCADE, - related_name='student', - limit_choices_to={'groups__name': 'Students'}, - ) - exam = models.ForeignKey( - 'ExamType', - on_delete=models.SET_NULL, - related_name='students', - null=True) + exam = models.ForeignKey( + 'ExamType', on_delete=models.SET_NULL, + related_name='students', null=True) + user = models.OneToOneField( + get_user_model(), unique=True, + on_delete=models.CASCADE, related_name='student') def score_per_submission(self): """ TODO: get rid of it and use an annotation. @@ -199,10 +206,10 @@ class Student(models.Model): s.type: s.feedback.score if hasattr(s, 'feedback') else 0 for s in self.submissions.all() }) - else: - return OrderedDict({ - t.name: 0 for t in SubmissionType.objects.all() - }) + + return OrderedDict({ + t.name: 0 for t in SubmissionType.objects.all() + }) @classmethod def get_overall_score_annotated_submission_list(cls): @@ -240,7 +247,7 @@ class Student(models.Model): return self.user.username class Meta: - verbose_name = "Student" + verbose_name = "Student" verbose_name_plural = "Student Set" @@ -260,8 +267,8 @@ class Test(models.Model): submission : ForeignKey The submission the tests where generated on """ - name = models.CharField(max_length=30) - label = models.CharField(max_length=50) + name = models.CharField(max_length=30) + label = models.CharField(max_length=50) annotation = models.TextField() submission = models.ForeignKey( 'submission', @@ -270,9 +277,9 @@ class Test(models.Model): ) class Meta: - verbose_name = "Test" + verbose_name = "Test" verbose_name_plural = "Tests" - unique_together = (('submission', 'name'),) + unique_together = (('submission', 'name'),) def __str__(self) -> str: return f'{self.name} {self.label}' @@ -291,8 +298,6 @@ class Submission(models.Model): ---------- seen_by_student : BooleanField True if the student saw his accepted feedback. - slug : SlugField - Slug for identification in domains student : OneToOneField The student how cause all of this text : TextField @@ -301,25 +306,21 @@ class Submission(models.Model): Relation to the type containing meta information """ seen_by_student = models.BooleanField(default=False) - text = models.TextField(blank=True) - slug = models.SlugField( - editable=False, - unique=True, - default=random_slug) - type = models.ForeignKey( + text = models.TextField(blank=True) + type = models.ForeignKey( SubmissionType, on_delete=models.PROTECT, related_name='submissions') - student = models.ForeignKey( + student = models.ForeignKey( Student, on_delete=models.CASCADE, related_name='submissions') class Meta: - verbose_name = "Submission" + verbose_name = "Submission" verbose_name_plural = "Submission Set" - unique_together = (('type', 'student'),) - ordering = ('type__name',) + unique_together = (('type', 'student'),) + ordering = ('type__name',) def __str__(self) -> str: return "Submission of type '{}' from Student '{}'".format( @@ -407,8 +408,6 @@ class Feedback(models.Model): score : PositiveIntegerField A score that has been assigned to he submission. Is final if it was accepted. - slug : SlugField - The slug for identification in urls STATUS : The status determines Description status : PositiveIntegerField @@ -422,15 +421,11 @@ class Feedback(models.Model): students submission, maybe with additional comments appended. """ - text = models.TextField() - score = models.PositiveIntegerField(default=0) - created = models.DateTimeField(auto_now_add=True) - modified = models.DateTimeField(auto_now=True) + text = models.TextField() + score = models.PositiveIntegerField(default=0) + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) - slug = models.SlugField( - editable=False, - unique=True, - default=random_slug) of_submission = models.OneToOneField( Submission, on_delete=models.CASCADE, @@ -439,13 +434,13 @@ class Feedback(models.Model): blank=False, null=False) of_tutor = models.ForeignKey( - User, + Tutor, on_delete=models.SET_NULL, related_name='feedback_list', blank=True, null=True) of_reviewer = models.ForeignKey( - User, + Reviewer, on_delete=models.SET_NULL, related_name='reviewed_submissions', blank=True, @@ -457,12 +452,12 @@ class Feedback(models.Model): OPEN, NEEDS_REVIEW, ACCEPTED, - ) = range(4) # this order matters + ) = range(4) # this order matters STATUS = ( - (EDITABLE, 'editable'), - (OPEN, 'request reassignment'), - (NEEDS_REVIEW, 'request review'), - (ACCEPTED, 'accepted'), + (EDITABLE, 'editable'), + (OPEN, 'request reassignment'), + (NEEDS_REVIEW, 'request review'), + (ACCEPTED, 'accepted'), ) status = models.IntegerField( choices=STATUS, @@ -478,11 +473,11 @@ class Feedback(models.Model): MANUAL, ) = range(5) ORIGIN = ( - (WAS_EMPTY, 'was empty'), + (WAS_EMPTY, 'was empty'), (FAILED_UNIT_TESTS, 'passed unittests'), - (DID_NOT_COMPILE, 'did not compile'), - (COULD_NOT_LINK, 'could not link'), - (MANUAL, 'created by a human. yak!'), + (DID_NOT_COMPILE, 'did not compile'), + (COULD_NOT_LINK, 'could not link'), + (MANUAL, 'created by a human. yak!'), ) origin = models.IntegerField( choices=ORIGIN, @@ -490,7 +485,7 @@ class Feedback(models.Model): ) class Meta: - verbose_name = "Feedback" + verbose_name = "Feedback" verbose_name_plural = "Feedback Set" def __str__(self) -> str: @@ -522,7 +517,7 @@ class Feedback(models.Model): """ return cls.objects.filter( Q(status=Feedback.OPEN) & - ~Q(of_tutor=user) # you shall not request your own feedback + ~Q(of_tutor=user) # you shall not request your own feedback ) @classmethod diff --git a/backend/core/permissions.py b/backend/core/permissions.py new file mode 100644 index 0000000000000000000000000000000000000000..3418f6dd13ad69513594f22ef6612261614d72fd --- /dev/null +++ b/backend/core/permissions.py @@ -0,0 +1,9 @@ +from rest_framework import permissions + +from core.models import Student + + +class IsStudent(permissions.BasePermission): + def has_permission(self, request, view): + user = request.user + return user.is_authenticated() and isinstance(user.get_associated_user(), Student) diff --git a/backend/core/serializers.py b/backend/core/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..8178ecfae6f841340d82c7e9afada2bee9dd3c52 --- /dev/null +++ b/backend/core/serializers.py @@ -0,0 +1,40 @@ +from rest_framework import serializers + +from core.models import ExamType, Feedback, Student, Submission + + +class ExamSerializer(serializers.ModelSerializer): + + class Meta: + model = ExamType + fields = ('module_reference', 'total_score', + 'pass_score', 'pass_only',) + + +class FeedbackSerializer(serializers.ModelSerializer): + + class Meta: + model = Feedback + fields = ('text', 'score') + + +class SubmissionSerializer(serializers.ModelSerializer): + feedback = serializers.ReadOnlyField(source='feedback.text') + score = serializers.ReadOnlyField(source='feedback.score') + type = serializers.ReadOnlyField(source='type.name') + full_score = serializers.ReadOnlyField(source='type.full_score') + + class Meta: + model = Submission + fields = ('type', 'text', 'feedback', 'score', 'full_score') + + +class StudentSerializer(serializers.ModelSerializer): + name = serializers.ReadOnlyField(source='user.fullname') + user = serializers.ReadOnlyField(source='user.username') + exam = ExamSerializer() + submissions = SubmissionSerializer(many=True) + + class Meta: + model = Student + fields = ('name', 'user', 'exam', 'submissions') diff --git a/core/tests.py b/backend/core/tests.py similarity index 51% rename from core/tests.py rename to backend/core/tests.py index c6fcdc756ca8c5a24efde9d895ac67c42f0baf36..f3290fbe0132092e58ed50fa7db0e04406b9b5e3 100644 --- a/core/tests.py +++ b/backend/core/tests.py @@ -1,26 +1,16 @@ -from django.contrib.auth.models import Group from django.test import TestCase -from core.models import Submission, SubmissionType, Feedback +from core.models import (Feedback, Reviewer, Student, Submission, + SubmissionType, Tutor) from util.importer import GradyUserFactory -def ensure_groups(): - Group.objects.get_or_create(name='Tutors') - Group.objects.get_or_create(name='Students') - Group.objects.get_or_create(name='Reviewers') - - class FeedbackTestCase(TestCase): factory = GradyUserFactory() - @classmethod - def setUpTestData(cls): - ensure_groups() - def setUp(self): - self.tutor = self.factory.make_tutor() + self.tutor = self.factory.make_tutor() self.student = self.factory.make_student() submission_type = SubmissionType.objects.create( @@ -44,26 +34,41 @@ class FactoryTestCase(TestCase): factory = GradyUserFactory() - @classmethod - def setUpTestData(cls): - ensure_groups() - def test_make_student(self): student = self.factory.make_student() - self.assertEqual(student.user.groups.filter(name='Students').count(), 1) + self.assertEqual(Student.objects.count(), 1) self.assertEqual(student.exam, None) self.assertEqual(len(str(student.matrikel_no)), 8) def test_can_create_reviewer(self): - self.assertTrue(Group.objects.get(name='Reviewers') - in self.factory.make_reviewer().groups.all()) + self.assertTrue(isinstance(self.factory.make_reviewer(), Reviewer)) + + def test_reviewer_appears_in_query_set(self): + self.assertIn(self.factory.make_reviewer(), Reviewer.objects.all()) def test_can_create_tutor(self): - self.assertTrue(Group.objects.get(name='Tutors') - in self.factory.make_tutor().groups.all()) + self.assertIn(self.factory.make_tutor(), Tutor.objects.all()) def test_can_create_student(self): - self.assertTrue(Group.objects.get(name='Students') - in self.factory.make_student().user.groups.all()) + self.assertIn(self.factory.make_student(), Student.objects.all()) + + +class AccountsTestCase(TestCase): + + factory = GradyUserFactory() + + def _test_user_obj_returns_correct_type(self, maker): + model = maker() + user = model.user + self.assertEqual(user.get_associated_user(), model) + + def test_user_obj_returns_correct_type_student(self): + self._test_user_obj_returns_correct_type(self.factory.make_student) + + def test_user_obj_returns_correct_type_tutor(self): + self._test_user_obj_returns_correct_type(self.factory.make_tutor) + + def test_user_obj_returns_correct_type_reviewer(self): + self._test_user_obj_returns_correct_type(self.factory.make_reviewer) diff --git a/backend/core/urls.py b/backend/core/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..f9b3345c6525e001776fd15597397f103d2dcf9b --- /dev/null +++ b/backend/core/urls.py @@ -0,0 +1,15 @@ +from django.conf.urls import url +from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from rest_framework_jwt.views import obtain_jwt_token + +from core import views + +urlpatterns = [ + url(r'^api/student/$', views.StudentApiView.as_view()), + url(r'^api/student/submission/(?P<pk>[0-9]+)$', views.SubmissionApiView.as_view()), + url(r'^api/student/submission/(?P<pk>[0-9]+)/feedback/$', views.FeedbackApiView.as_view()), + + url(r'^api-token-auth/', obtain_jwt_token) +] + +urlpatterns += staticfiles_urlpatterns() diff --git a/backend/core/views.py b/backend/core/views.py new file mode 100644 index 0000000000000000000000000000000000000000..2932ec09bb16aebe08c22bfdfa567ca288d737fd --- /dev/null +++ b/backend/core/views.py @@ -0,0 +1,35 @@ +import logging + +from rest_framework.generics import RetrieveAPIView + +from core.permissions import IsStudent +from core.serializers import (FeedbackSerializer, StudentSerializer, + SubmissionSerializer) + +log = logging.getLogger(__name__) + + + +class StudentApiView(RetrieveAPIView): + permission_classes = (IsStudent,) + + def get_object(self): + log.debug("Serializing student of user '%s'", self.request.user.username) + return self.request.user.student + serializer_class = StudentSerializer + + +class SubmissionApiView(RetrieveAPIView): + permission_classes = (IsStudent,) + + def get_queryset(self): + return self.request.user.student.submissions + serializer_class = SubmissionSerializer + + +class FeedbackApiView(RetrieveAPIView): + permission_classes = (IsStudent,) + + def get_queryset(self): + return [submission.feedback for submission in self.request.user.submissions] + serializer_class = FeedbackSerializer diff --git a/delbert.py b/backend/delbert.py similarity index 93% rename from delbert.py rename to backend/delbert.py index d97add4cdc76dd8c8a857ba4c502994d2a1c4d3d..557260f5c0a257d7d76e6fbfca6304aae899b10c 100644 --- a/delbert.py +++ b/backend/delbert.py @@ -1,18 +1,20 @@ import argparse import csv +import json import os -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'grady.settings') import secrets import sys -import json import django -django.setup() - from django.contrib.auth.models import User -from core.models import Student, Submission import util.importer +from core.models import Student, Submission + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'grady.settings') + +django.setup() + def parseme(): parser = argparse.ArgumentParser() @@ -81,7 +83,7 @@ def parseme(): return parser.parse_args() -def handle_passwordlist(output=sys.stdout, instance="", **kwargs): +def handle_passwordlist(output=sys.stdout, instance=""): with open('/usr/share/dict/words') as words: choose_from = list({word.strip().lower() for word in words if 5 < len(word) < 8}) @@ -99,7 +101,7 @@ def handle_passwordlist(output=sys.stdout, instance="", **kwargs): student.user.username, password, instance]) -def handle_enableusers(switch, exclude, include, **kwargs): +def handle_enableusers(switch, exclude, include): if include: for user in User.objects.filter(username__in=include): @@ -111,7 +113,7 @@ def handle_enableusers(switch, exclude, include, **kwargs): user.save() -def handle_replaceusernames(matno2username_dict, **kwargs): +def handle_replaceusernames(matno2username_dict): matno2username = json.JSONDecoder().decode(matno2username_dict.read()) for student in Student.objects.all(): if student.matrikel_no in matno2username: @@ -120,12 +122,12 @@ def handle_replaceusernames(matno2username_dict, **kwargs): student.user.save() -def handle_extractsubmissions(output, **kwargs): +def handle_extractsubmissions(): for submission in Submission.objects.filter(feedback__isnull=False).order_by('type'): print(submission.feedback.score, repr(submission.text), file=open(str(submission.type).replace(' ', '_'), 'a')) -def handle_importer(**kwargs): +def handle_importer(): util.importer.start() def main(): diff --git a/docs/Database Design/Entity Relation Model.erdplus b/backend/docs/Database Design/Entity Relation Model.erdplus similarity index 100% rename from docs/Database Design/Entity Relation Model.erdplus rename to backend/docs/Database Design/Entity Relation Model.erdplus diff --git a/docs/Database Design/Relational Schema.erdplus b/backend/docs/Database Design/Relational Schema.erdplus similarity index 100% rename from docs/Database Design/Relational Schema.erdplus rename to backend/docs/Database Design/Relational Schema.erdplus diff --git a/docs/Database Design/er-model.graphml b/backend/docs/Database Design/er-model.graphml similarity index 100% rename from docs/Database Design/er-model.graphml rename to backend/docs/Database Design/er-model.graphml diff --git a/docs/Database Design/erdplus-diagram-pdf-export.pdf b/backend/docs/Database Design/erdplus-diagram-pdf-export.pdf similarity index 100% rename from docs/Database Design/erdplus-diagram-pdf-export.pdf rename to backend/docs/Database Design/erdplus-diagram-pdf-export.pdf diff --git a/docs/Database Design/erdplus-er-model-export.pdf b/backend/docs/Database Design/erdplus-er-model-export.pdf similarity index 100% rename from docs/Database Design/erdplus-er-model-export.pdf rename to backend/docs/Database Design/erdplus-er-model-export.pdf diff --git a/docs/core_uml.png b/backend/docs/core_uml.png similarity index 100% rename from docs/core_uml.png rename to backend/docs/core_uml.png diff --git a/grady/__init__.py b/backend/grady/__init__.py similarity index 100% rename from grady/__init__.py rename to backend/grady/__init__.py diff --git a/grady/settings/__init__.py b/backend/grady/settings/__init__.py similarity index 100% rename from grady/settings/__init__.py rename to backend/grady/settings/__init__.py diff --git a/grady/settings/default.py b/backend/grady/settings/default.py similarity index 62% rename from grady/settings/default.py rename to backend/grady/settings/default.py index 758f71026e5bd6eff17aa11205b83481324a4df0..86e0c94956f52ceb7b459c8d8e015d73c4825a6c 100644 --- a/grady/settings/default.py +++ b/backend/grady/settings/default.py @@ -10,6 +10,7 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.10/ref/settings/ """ +import datetime import os from django.contrib.messages import constants as messages @@ -39,11 +40,14 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django_extensions', - 'compressor', 'core', + 'rest_framework', + 'corsheaders', ] MIDDLEWARE = [ + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -71,6 +75,7 @@ TEMPLATES = [ }, ] + WSGI_APPLICATION = 'grady.wsgi.application' @@ -88,21 +93,6 @@ DATABASES = { }, } -# Password validation -# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ @@ -116,7 +106,9 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ - +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'node_modules'), +) STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/') @@ -145,5 +137,74 @@ COMPRESS_OFFLINE = True STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', - 'compressor.finders.CompressorFinder', ) + +AUTH_USER_MODEL = 'core.UserAccount' +AUTH_PASSWORD_VALIDATORS = [] +CORS_ORIGIN_WHITELIST = ( + 'localhost:8080' +) + +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.BasicAuthentication', + ), +} + +JWT_AUTH = { + 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=600), +} + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + 'django.server': { + 'datefmt': '%d/%b/%Y %H:%M:%S', + 'format': '[%(asctime)s] %(levelname)-10s %(name)-20s %(message)s', + }, + 'core': { + 'datefmt': '%d/%b/%Y %H:%M:%S', + 'format': '[%(asctime)s] %(levelname)-10s %(name)-20s "%(message)s"', + }, + }, + 'filters': { + 'require_debug_true': { + '()': 'django.utils.log.RequireDebugTrue', + }, + }, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'filters': ['require_debug_true'], + 'class': 'logging.StreamHandler', + 'formatter': 'core' + }, + 'django': { + 'level': 'INFO', + 'class': 'logging.StreamHandler', + 'formatter': 'django.server' + }, + 'mail_admins': { # TODO: configuration + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + } + }, + 'loggers': { + 'django': { + 'handlers': ['django'], + }, + 'django.request': { + 'handlers': ['django'], + }, + 'core': { + 'handlers': ['console', 'mail_admins'], + 'level': 'DEBUG', + } + } +} diff --git a/grady/settings/live.py b/backend/grady/settings/live.py similarity index 56% rename from grady/settings/live.py rename to backend/grady/settings/live.py index 0bf021be6feb66da4ea964ea1e0d0d6231118fbc..2f3bfe34cbc7ee4a56a476881f397bf744af5135 100644 --- a/grady/settings/live.py +++ b/backend/grady/settings/live.py @@ -9,7 +9,6 @@ X_FRAME_OPTIONS = 'DENY' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False -COMPRESS_ENABLED = not DEBUG # adjust this setting to your needs ALLOWED_HOSTS = ['localhost', '.grady.janmax.org'] @@ -25,3 +24,21 @@ DATABASES = { 'PORT': '5432', }, } + +# Password validation +# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, +] diff --git a/grady/urls.py b/backend/grady/urls.py similarity index 85% rename from grady/urls.py rename to backend/grady/urls.py index ff39cb407bdfccf3ed42992a532d4120e3ed887b..9acdd9b0e47126124006bc7b2ee0445a4388a42f 100644 --- a/grady/urls.py +++ b/backend/grady/urls.py @@ -20,3 +20,8 @@ urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('core.urls')) ] + +urlpatterns += [ + url(r'^api-auth/', include('rest_framework.urls', + namespace='rest_framework')), +] diff --git a/grady/wsgi.py b/backend/grady/wsgi.py similarity index 100% rename from grady/wsgi.py rename to backend/grady/wsgi.py diff --git a/manage.py b/backend/manage.py similarity index 100% rename from manage.py rename to backend/manage.py diff --git a/requirements.txt b/backend/requirements.txt similarity index 62% rename from requirements.txt rename to backend/requirements.txt index 221a034a22f7794d23f51564822858df3d35ba0b..9f84b378ab58611f325b862ad2fb964b3d9144cd 100644 --- a/requirements.txt +++ b/backend/requirements.txt @@ -1,9 +1,12 @@ Django~=1.11.3 django-extensions~=1.7.7 djangorestframework~=3.6.3 +djangorestframework-jwt~=1.11.0 django_compressor~=2.1.1 gunicorn~=19.7.0 psycopg2~=2.7.1 xlrd~=1.0.0 pytest-cov~=2.5.1 -pylint~=1.7.4 +prospector~=0.12.7 +django-cors-headers~=2.1.0 +pre-commit~=1.4.1 \ No newline at end of file diff --git a/scripts/README.rst b/backend/scripts/README.rst similarity index 100% rename from scripts/README.rst rename to backend/scripts/README.rst diff --git a/scripts/compile.py b/backend/scripts/compile.py similarity index 100% rename from scripts/compile.py rename to backend/scripts/compile.py diff --git a/util/__init__.py b/backend/util/__init__.py similarity index 100% rename from util/__init__.py rename to backend/util/__init__.py diff --git a/util/convert.py b/backend/util/convert.py similarity index 100% rename from util/convert.py rename to backend/util/convert.py diff --git a/util/importer.py b/backend/util/importer.py similarity index 78% rename from util/importer.py rename to backend/util/importer.py index 8e341e6348f21a874e3d48e1fde601660abf853d..299f4ae547c1b8e1a8a9dcd2568bf3ca29d0b407 100644 --- a/util/importer.py +++ b/backend/util/importer.py @@ -6,25 +6,24 @@ import readline import secrets from typing import Callable -from django.contrib.auth.models import Group, User - import util.convert import util.processing -from core.models import (ExamType, Feedback, Student, Submission, - SubmissionType, Test) +from core.models import UserAccount as User +from core.models import (ExamType, Feedback, Reviewer, Student, Submission, + SubmissionType, Test, Tutor) from util.messages import info, warn from util.processing import EmptyTest -STUDENTS = 'Students' -TUTORS = 'Tutors' -REVIEWERS = 'Reviewers' +STUDENTS = 'students' +TUTORS = 'tutors' +REVIEWERS = 'reviewers' -HISTFILE = '.importer_history' -RECORDS = '.importer' +HISTFILE = '.importer_history' +RECORDS = '.importer' PASSWORDS = '.importer_passwords' YES = 'Y/n' -NO = 'y/N' +NO = 'y/N' valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} @@ -98,40 +97,32 @@ def store_password(username, groupname, password): with open(PASSWORDS, 'w') as passwd_file: storage.write(passwd_file) + class GradyUserFactory: def __init__(self, password_generator_func=get_xkcd_password, *args, **kwargs): self.password_generator_func = password_generator_func @staticmethod - def get_random_name(prefix='', suffix='', k=1): + def _get_random_name(prefix='', suffix='', k=1): return ''.join((prefix, get_xkcd_password(k), suffix)) - def make_default_user(self, username, **kwargs): - return User.objects.update_or_create(username=username, defaults=kwargs) - - def make_user_in_group(self, username, groupname, store_pw=False, **kwargs): + def _make_base_user(self, username, groupname, store_pw=False, **kwargs): """ This is a specific wrapper for the django update_or_create method of objects. * A new user is created and password and group are set accordingly * If the user was there before password is NOT change but group is. A user must only have one group. - Args: - username (str): the username is the login name - group (Group object): the (only) group the user should belong to - **kwargs: more attributes for user creation - Returns: (User object, str): The user object that was added to the group and the password of that user if it was created. """ username = username.strip() - user, created = self.make_default_user( + user, created = User.objects.update_or_create( username=username, - **kwargs - ) + defaults=kwargs) if created: password = self.password_generator_func() @@ -141,47 +132,52 @@ class GradyUserFactory: if created and store_pw: store_password(username, groupname, password) - group = Group.objects.get(name=groupname) - user.groups.clear() # remove all other groups - user.groups.add(group) - user.save() - return user + def _get_user_model_for_group(self, groupname): + """ Returns the model class for a usergroup """ + return { + STUDENTS: Student, + TUTORS: Tutor, + REVIEWERS: Reviewer, + }[groupname] - def make_user_in_student_group(self, username, **kwargs): - return self.make_user_in_group(username, STUDENTS, **kwargs) + def _make_user_generic(self, username, groupname, **kwargs): + """ Provides a model with a associated user but without any defaults + """ - def make_student(self, username=None, name='__name', matrikel_no=None, exam=None, **kwargs): if not username: - username = self.get_random_name(prefix='student_') + username = self._get_random_name(prefix=groupname.lower() + '_') - user = self.make_user_in_student_group(username, **kwargs) + model = self._get_user_model_for_group(groupname) + user = self._make_base_user(username, groupname, **kwargs) - student, _ = Student.objects.update_or_create( - name=name, - defaults={ - 'user': user, - 'exam': exam, - # TODO: find an elegant way to include optionals iff they exist - } - ) + generic_user, _ = model.objects.get_or_create(user=user) - return student + return generic_user + + def make_student(self, username=None, matrikel_no=None, exam=None, **kwargs): + """ Creates a student. Defaults can be passed via kwargs like in + relation managers objects.update method. """ + user = self._make_user_generic(username, STUDENTS, **kwargs) + if matrikel_no: + user.objects.update(matrikel_no=matrikel_no) + if exam: + user.objects.update(exam=exam) + return user def make_tutor(self, username=None, **kwargs): - if not username: - username = self.get_random_name(prefix='tutor_') - return self.make_user_in_group(username, TUTORS, **kwargs) + """ Creates or updates a tutor if needed with defaults """ + return self._make_user_generic(username, TUTORS, **kwargs) def make_reviewer(self, username=None, **kwargs): - if not username: - username = self.get_random_name(prefix='reviewer_') - return self.make_user_in_group(username, REVIEWERS, **kwargs) + """ Creates or updates a reviewer if needed with defaults """ + return self._make_user_generic(username, REVIEWERS, **kwargs) +# TODO more factories def add_user(username, group, **kwargs): - user = GradyUserFactory().make_user_in_group( + user = GradyUserFactory()._make_base_user( username, group, store_pw=True, **kwargs ) @@ -190,10 +186,10 @@ def add_user(username, group, **kwargs): def add_student(username, email, submissions, **kwargs): - user = add_user(username, STUDENTS, email=email) - student, _ = Student.objects.update_or_create( + user = add_user(username, STUDENTS, email=email) + student, _ = Student.objects.update_or_create( user=user, - defaults={'user' : user, **kwargs} + defaults={'user': user, **kwargs} ) return student @@ -206,7 +202,7 @@ def add_submission(student_obj, code, tests, type): submission_obj, _ = Submission.objects.update_or_create( type=submission_type, student=student_obj, - defaults={'text' : code} + defaults={'text': code} ) auto_correct, _ = User.objects.get_or_create( @@ -232,11 +228,11 @@ def add_submission(student_obj, code, tests, type): Feedback.objects.update_or_create( of_submission=submission_obj, defaults={ - 'of_tutor' : auto_correct, - 'score' : 0, - 'text' : test_obj.label, - 'origin' : FEEDBACK_MAPPER[test_obj.name], - 'status' : Feedback.ACCEPTED if test_obj.name == EmptyTest.__name__ else Feedback.EDITABLE, + 'of_tutor': auto_correct, + 'score': 0, + 'text': test_obj.label, + 'origin': FEEDBACK_MAPPER[test_obj.name], + 'status': Feedback.ACCEPTED if test_obj.name == EmptyTest.__name__ else Feedback.EDITABLE, } ) @@ -262,7 +258,7 @@ def call_loader(func: Callable) -> None: i(f'{func.__name__} has already been processed once. Proceed anyway?', NO): return - func() # This executes the specified loader + func() # This executes the specified loader with open(RECORDS, 'a') as records_f: records_f.write(func.__name__) @@ -277,7 +273,7 @@ def do_convert_xls(): if not ans: return - infile = i('Please provide the path to the .xls file', is_file=True) + infile = i('Please provide the path to the .xls file', is_file=True) outfile = i('Where should the output go?', 'submissons.json') json_dict = util.convert.converter(infile) @@ -287,7 +283,7 @@ def do_convert_xls(): def do_load_submission_types(): print( - '''For the following import you need three files: + '''For the following import you need three files: 1) A .csv file where the columns are: id, name, score 2) A path to a directory where I can find sample solutions named @@ -316,9 +312,9 @@ def do_load_submission_types(): path = i('Where are your files located?', '.', is_path=True) with chdir_context(path): - submission_types_csv = i('CSV file', 'submission_types.csv') - lsg_dir = i('solution dir', 'code-lsg') - desc_dir = i('descriptions dir', 'html') + submission_types_csv = i('CSV file', 'submission_types.csv') + lsg_dir = i('solution dir', 'code-lsg') + desc_dir = i('descriptions dir', 'html') with open(submission_types_csv, encoding='utf-8') as tfile: csv_rows = [row for row in csv.reader(tfile)] @@ -328,11 +324,11 @@ def do_load_submission_types(): with \ open(os.path.join(lsg_dir, tid + '-lsg.c'), encoding='utf-8') as lsg,\ open(os.path.join(desc_dir, tid + '.html'), encoding='utf-8') as desc: - data={ - 'name' : name, - 'description' : desc.read(), - 'solution' : lsg.read(), - 'full_score' : int(score), + data = { + 'name': name, + 'description': desc.read(), + 'solution': lsg.read(), + 'full_score': int(score), } _, created = SubmissionType.objects.update_or_create( name=name, @@ -364,7 +360,7 @@ def do_load_module_descriptions(): for row in csv_rows: data = { - field : kind(data) for field, kind, data in zip( + field: kind(data) for field, kind, data in zip( ('module_reference', 'total_score', 'pass_score', 'pass_only'), (str, int, int, lambda x: x == 'yes'), (col.strip() for col in row) @@ -418,13 +414,13 @@ def do_load_submissions(): print() exam = i('Choose wisely') - exam = {'exam' : exam_query_set[int(exam)]} + exam = {'exam': exam_query_set[int(exam)]} with open(file) as submission_file: submissions = json.JSONDecoder().decode(submission_file.read()) for username, data in submissions.items(): - student_obj = add_student(username, **exam, **data) + student_obj = make_student(username, **exam, **data) for submission_obj in data['submissions']: add_submission(student_obj, **submission_obj) @@ -433,7 +429,7 @@ def do_load_submissions(): def do_load_tutors(): print('Please import tutor users by providing one name per line') - tutors = i('List of tutors', 'tutors', is_file=True) + tutors = i('List of tutors', 'tutors', is_file=True) with open(tutors) as tutors_f: add_user_list(tutors_f, TUTORS) diff --git a/util/messages.py b/backend/util/messages.py similarity index 100% rename from util/messages.py rename to backend/util/messages.py diff --git a/util/processing.py b/backend/util/processing.py similarity index 100% rename from util/processing.py rename to backend/util/processing.py diff --git a/util/testcases.py b/backend/util/testcases.py similarity index 100% rename from util/testcases.py rename to backend/util/testcases.py diff --git a/yarn.lock b/backend/yarn.lock similarity index 100% rename from yarn.lock rename to backend/yarn.lock diff --git a/core/admin.py b/core/admin.py deleted file mode 100644 index 300130b8b737f58e64454245a483d9f13d00d77f..0000000000000000000000000000000000000000 --- a/core/admin.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib import admin - -from .models import Feedback, Student, Submission, SubmissionType, Test - -# Register your models here. - -admin.site.register(SubmissionType) -admin.site.register(Feedback) -admin.site.register(Student) -admin.site.register(Test) -admin.site.register(Submission) diff --git a/core/custom_annotations.py b/core/custom_annotations.py deleted file mode 100644 index 5296b703b40e7e3f57135c48efa1cc540654b40a..0000000000000000000000000000000000000000 --- a/core/custom_annotations.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.contrib.auth.decorators import user_passes_test - - -"""I collect custom decorators here that I use for the simple premission system - -Currently the following options are available - - group_required - - in_groups -""" - - -def in_groups(user, group_list): - return bool(user.groups.filter(name__in=group_list)) or user.is_superuser - - -def group_required(*group_names): - """Requires user membership in at least one of the groups passed in. Should - only be used in annotations - """ - def _in_groups(u): - if u.is_authenticated(): - return in_groups(u, group_names) - return user_passes_test(_in_groups) diff --git a/core/fixtures/testdata-core.json b/core/fixtures/testdata-core.json deleted file mode 100644 index 28b9bea58d4a332e87c9e0c4b7dc97402a89daea..0000000000000000000000000000000000000000 --- a/core/fixtures/testdata-core.json +++ /dev/null @@ -1,88 +0,0 @@ -[ - { - "fields": { - "full_score": 10, - "name": "Aufgabe 01", - "solution": "solution", - "slug": "brezmaphgocfuikw", - "description": "description" - }, - "model": "core.submissiontype", - "pk": 1 - }, - { - "fields": { - "full_score": 20, - "name": "Aufgabe 02", - "solution": "solution", - "slug": "zbjfwldsuhqgxvmn", - "description": "description" - }, - "model": "core.submissiontype", - "pk": 2 - }, - { - "fields": { - "has_logged_in": false, - "matrikel_no": "12345678", - "name": "Student 01 Vorname und Nachname", - "user": 4 - }, - "model": "core.student", - "pk": 1 - }, - { - "fields": { - "has_logged_in": false, - "matrikel_no": "87654321", - "name": "Student 02 Vorname und Nachname", - "user": 5 - }, - "model": "core.student", - "pk": 2 - }, - { - "fields": { - "seen_by_student": false, - "slug": "qgleatcwzfxsdnjr", - "student": 1, - "text": "function generate(timeout){\r\n\r\n\t$('#menu_button_img').attr('src', 'style/menu_blink.gif'); \r\n\r\n\tif(timeout == 0)\t\t\t\t\t\t\t\t\r\n\t\t$('#config_form').attr('action', $('#config_form').attr('action') + '#title'); \t\t\t\t// show directly the question\r\n\telse\r\n\t\ttimeout = 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// disable timeout\r\n\t\r\n\tsetTimeout(function(){ $('#config_form').submit(); }, timeout);\r\n\r\n}", - "type": 1 - }, - "model": "core.submission", - "pk": 1 - }, - { - "fields": { - "seen_by_student": false, - "slug": "mrthqgsloaydjfnc", - "student": 1, - "text": "function showTextEditor(){\r\n\r\n\t$('.ilc_question_Standard').hide('slow');\r\n\t$('.ilc_question_ml_Standard').hide('slow');\r\n\t$('.text_editor').show('slow');\r\n\t\r\n}\r\n\r\nfunction showConfig(){\r\n\r\n\t$('#config_wrapper').animate(\r\n\t\t{\r\n\t\t\tright: ($('#config_wrapper').css('right') == '0px' ? '-322px' : '0px')\r\n\t\t}, \r\n\t500);\r\n\r\n}", - "type": 2 - }, - "model": "core.submission", - "pk": 2 - }, - { - "fields": { - "seen_by_student": false, - "slug": "hunkgevtcfdobyxw", - "student": 2, - "text": "$(document).keydown(function(evt){\r\n\r\n\tif(evt.which == 9){\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// #9 = TAB\r\n\t\tgenerate(0);\r\n\t\tevt.preventDefault();\r\n\t}\r\n\t\r\n});", - "type": 2 - }, - "model": "core.submission", - "pk": 3 - }, - { - "fields": { - "seen_by_student": false, - "slug": "gurvbyzxjfmhdiep", - "student": 2, - "text": "function showTextEditor(){\r\n\r\n\t$('.ilc_question_Standard').hide('slow');\r\n\t$('.ilc_question_ml_Standard').hide('slow');\r\n\t$('.text_editor').show('slow');\r\n\t\r\n}\r\n\r\nfunction showConfig(){\r\n\r\n\t$('#config_wrapper').animate(\r\n\t\t{\r\n\t\t\tright: ($('#config_wrapper').css('right') == '0px' ? '-322px' : '0px')\r\n\t\t}, \r\n\t500);\r\n\r\n}", - "type": 1 - }, - "model": "core.submission", - "pk": 4 - } -] diff --git a/core/fixtures/testdata-groups.json b/core/fixtures/testdata-groups.json deleted file mode 100644 index e0c5e95cad7a721f77dcb33e8aab4d2e61deac9d..0000000000000000000000000000000000000000 --- a/core/fixtures/testdata-groups.json +++ /dev/null @@ -1 +0,0 @@ -[{"model": "auth.group", "pk": 1, "fields": {"name": "Students", "permissions": []}}, {"model": "auth.group", "pk": 2, "fields": {"name": "Reviewers", "permissions": []}}, {"model": "auth.group", "pk": 3, "fields": {"name": "Tutors", "permissions": []}}] \ No newline at end of file diff --git a/core/fixtures/testdata-user.json b/core/fixtures/testdata-user.json deleted file mode 100644 index 34cf27c2acc807ae2223d5c3dbe77373daa68d61..0000000000000000000000000000000000000000 --- a/core/fixtures/testdata-user.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "fields": { - "date_joined": "2017-06-08T15:07:10.023Z", - "email": "", - "first_name": "", - "groups": [], - "is_active": true, - "is_staff": true, - "is_superuser": true, - "last_login": "2017-06-08T15:07:30.105Z", - "last_name": "", - "password": "pbkdf2_sha256$30000$hirLzfSDQ9f3$CNgyfYKEzxYHkhx3SE5gde3ZeTRsJRYmdr1AMlYIwtg=", - "user_permissions": [], - "username": "doncamillo" - }, - "model": "auth.user", - "pk": 1 - }, - { - "fields": { - "date_joined": "2017-06-08T15:27:53Z", - "email": "", - "first_name": "", - "groups": [ - 2 - ], - "is_active": true, - "is_staff": false, - "is_superuser": false, - "last_login": null, - "last_name": "", - "password": "pbkdf2_sha256$30000$GMuQITImWNbK$i1FftkDWk2fmjHyv7VThV40DzkdfzS8tbnT4uswzfRA=", - "user_permissions": [], - "username": "reviewer" - }, - "model": "auth.user", - "pk": 2 - }, - { - "fields": { - "date_joined": "2017-06-08T15:28:24.320Z", - "email": "", - "first_name": "", - "groups": [], - "is_active": true, - "is_staff": false, - "is_superuser": false, - "last_login": null, - "last_name": "", - "password": "pbkdf2_sha256$30000$JuuBxTeONPuc$Gfbo+MkZmxWJpVVOSf66Sz7Mvz/Of0WFXrosbSeQv24=", - "user_permissions": [], - "username": "tutor" - }, - "model": "auth.user", - "pk": 3 - }, - { - "fields": { - "date_joined": "2017-06-08T15:29:05Z", - "email": "", - "first_name": "", - "groups": [ - 1 - ], - "is_active": true, - "is_staff": false, - "is_superuser": false, - "last_login": null, - "last_name": "", - "password": "pbkdf2_sha256$30000$YaJGFEnSEejd$2dmLmeVFyhEZda/YWwJ/zRMvAbnULYA90IrakJsMYCw=", - "user_permissions": [], - "username": "student01" - }, - "model": "auth.user", - "pk": 4 - }, - { - "fields": { - "date_joined": "2017-06-08T15:31:44Z", - "email": "", - "first_name": "", - "groups": [ - 1 - ], - "is_active": true, - "is_staff": false, - "is_superuser": false, - "last_login": null, - "last_name": "", - "password": "pbkdf2_sha256$30000$SR5pr6OUXScN$NYQiX7J5wgjW8t4gROq46oqRPVWoGd+J1Od4ZWzkN3A=", - "user_permissions": [], - "username": "student02" - }, - "model": "auth.user", - "pk": 5 - } -] diff --git a/core/forms.py b/core/forms.py deleted file mode 100644 index 766cf783951d4692af986f8786f9e9c45ded71f6..0000000000000000000000000000000000000000 --- a/core/forms.py +++ /dev/null @@ -1,39 +0,0 @@ -from django.forms import CharField, ModelForm, Textarea, ValidationError - -from core.models import Feedback - - -class FeedbackForm(ModelForm): - text = CharField( - widget=Textarea( - attrs={ - 'name': 'text', - 'id': 'id_text', - } - ), - label='', - required=False, - ) - - def clean(self): - cleaned_data = super().clean() - - full_score = self.instance.of_submission.type.full_score - if not cleaned_data.get("score") <= full_score: - raise ValidationError( - "Score too high. Maximum score is %(max_score)d", - code='over_max_score', - params={'max_score': full_score}, - ) - - if not cleaned_data.get("text"): - cleaned_data["status"] = Feedback.EDITABLE - raise ValidationError( - "Feedback should not be empty", - code="is_empty", - ) - - class Meta: - model = Feedback - auto_id = False - fields = ('text', 'score', 'status') diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py deleted file mode 100644 index 41d82568a409984d883a048591eb3171deb98e6a..0000000000000000000000000000000000000000 --- a/core/migrations/0001_initial.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.6 on 2017-04-05 20:11 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import core.models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Feedback', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('text', models.TextField()), - ('slug', models.SlugField(default=core.models.random_slug, editable=False, unique=True)), - ('score', models.PositiveIntegerField(default=0)), - ('status', models.CharField(choices=[('I', 'editable'), ('A', 'accepted'), ('R', 'request review'), ('O', 'request reassignment')], default='I', max_length=1)), - ('origin', models.CharField(choices=[('E', 'was empty'), ('UT', 'passed unittests'), ('CF', 'did not compile'), ('LF', 'could not link'), ('M', 'created by a human. yak!')], default='M', max_length=2)), - ('of_reviewer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviewed_submissions', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Feedback', - 'verbose_name_plural': 'Feedback Set', - }, - ), - migrations.CreateModel( - name='Student', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('matrikel_no', models.CharField(default=core.models.random_matrikel_no, max_length=8, unique=True)), - ('name', models.CharField(default='__no_name__', max_length=50)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Student', - 'verbose_name_plural': 'Student Set', - }, - ), - migrations.CreateModel( - name='Submission', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('slug', models.SlugField(default=core.models.random_slug, editable=False, unique=True)), - ('seen', models.BooleanField(default=False)), - ('text', models.TextField(blank=True)), - ('pre_corrections', models.TextField(blank=True)), - ('final_feedback', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Feedback')), - ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Student')), - ], - options={ - 'verbose_name': 'Submission', - 'verbose_name_plural': 'Submission Set', - }, - ), - migrations.CreateModel( - name='SubmissionType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=50, unique=True)), - ('slug', models.SlugField(default=core.models.random_slug, editable=False, unique=True)), - ('full_score', models.PositiveIntegerField(default=0)), - ('task_description', models.TextField()), - ('possible_solution', models.TextField()), - ('correction_guideline', models.TextField()), - ], - options={ - 'verbose_name': 'SubmissionType', - 'verbose_name_plural': 'SubmissionType Set', - }, - ), - migrations.AddField( - model_name='submission', - name='type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.SubmissionType'), - ), - migrations.AddField( - model_name='feedback', - name='of_submission', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to='core.Submission'), - ), - migrations.AddField( - model_name='feedback', - name='of_tutor', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='corrected_submissions', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0002_auto_20170412_1447.py b/core/migrations/0002_auto_20170412_1447.py deleted file mode 100644 index f92b185386910b6e770fa8403e32b8b2502ba24d..0000000000000000000000000000000000000000 --- a/core/migrations/0002_auto_20170412_1447.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-12 14:47 -from __future__ import unicode_literals - -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='created', - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), - preserve_default=False, - ), - migrations.AddField( - model_name='feedback', - name='modified', - field=models.DateTimeField(auto_now=True), - ), - ] diff --git a/core/migrations/0003_auto_20170412_1507.py b/core/migrations/0003_auto_20170412_1507.py deleted file mode 100644 index be676b4c00bd6fb945f1099b2cec7ff3da2fff94..0000000000000000000000000000000000000000 --- a/core/migrations/0003_auto_20170412_1507.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-12 15:07 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0002_auto_20170412_1447'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='origin', - field=models.IntegerField(choices=[(0, 'was empty'), (1, 'passed unittests'), (2, 'did not compile'), (3, 'could not link'), (4, 'created by a human. yak!')], default=4), - ), - migrations.AlterField( - model_name='feedback', - name='status', - field=models.IntegerField(choices=[(0, 'editable'), (1, 'accepted'), (2, 'request review'), (3, 'request reassignment')], default=0), - ), - ] diff --git a/core/migrations/0004_auto_20170412_1704.py b/core/migrations/0004_auto_20170412_1704.py deleted file mode 100644 index fc41092bfad30df26d6800d9121ba449a886f8dc..0000000000000000000000000000000000000000 --- a/core/migrations/0004_auto_20170412_1704.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-12 17:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0003_auto_20170412_1507'), - ] - - operations = [ - migrations.AddField( - model_name='student', - name='logged_in', - field=models.BooleanField(default=False), - ), - migrations.AlterField( - model_name='feedback', - name='status', - field=models.IntegerField(choices=[(0, 'editable'), (1, 'request reassignment'), (2, 'request review'), (3, 'accepted')], default=0), - ), - ] diff --git a/core/migrations/0005_auto_20170413_0124.py b/core/migrations/0005_auto_20170413_0124.py deleted file mode 100644 index b25f249e46b66aab720450b013058e13bc31beda..0000000000000000000000000000000000000000 --- a/core/migrations/0005_auto_20170413_0124.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-13 01:24 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0004_auto_20170412_1704'), - ] - - operations = [ - migrations.RemoveField( - model_name='submission', - name='final_feedback', - ), - migrations.AlterField( - model_name='feedback', - name='of_submission', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'), - ), - ] diff --git a/core/migrations/0006_auto_20170413_1102.py b/core/migrations/0006_auto_20170413_1102.py deleted file mode 100644 index 38f11223befeacfbab678dc0f0be7aa5b3bea637..0000000000000000000000000000000000000000 --- a/core/migrations/0006_auto_20170413_1102.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-13 11:02 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0005_auto_20170413_0124'), - ] - - operations = [ - migrations.RenameField( - model_name='student', - old_name='logged_in', - new_name='has_logged_in', - ), - ] diff --git a/core/migrations/0007_auto_20170522_1827.py b/core/migrations/0007_auto_20170522_1827.py deleted file mode 100644 index fb6c0578ab3202c63ea9376750c9fff4fc7b54af..0000000000000000000000000000000000000000 --- a/core/migrations/0007_auto_20170522_1827.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-05-22 18:27 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0006_auto_20170413_1102'), - ] - - operations = [ - migrations.AlterField( - model_name='submission', - name='student', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.Student'), - ), - migrations.AlterUniqueTogether( - name='submission', - unique_together=set([('type', 'student')]), - ), - ] diff --git a/core/migrations/0008_auto_20170522_1834.py b/core/migrations/0008_auto_20170522_1834.py deleted file mode 100644 index 7eb42fad8d01012fdfeba12b7f068dde59af52fe..0000000000000000000000000000000000000000 --- a/core/migrations/0008_auto_20170522_1834.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-05-22 18:34 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0007_auto_20170522_1827'), - ] - - operations = [ - migrations.RenameField( - model_name='submission', - old_name='seen', - new_name='seen_by_student', - ), - migrations.RemoveField( - model_name='submissiontype', - name='correction_guideline', - ), - ] diff --git a/core/migrations/0009_auto_20170710_1308.py b/core/migrations/0009_auto_20170710_1308.py deleted file mode 100644 index 0a06d82f61967fa295b5b9783e80a2f5a2cfbf62..0000000000000000000000000000000000000000 --- a/core/migrations/0009_auto_20170710_1308.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-10 13:08 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0008_auto_20170522_1834'), - ] - - operations = [ - migrations.RenameField( - model_name='submissiontype', - old_name='task_description', - new_name='description', - ), - migrations.RenameField( - model_name='submissiontype', - old_name='possible_solution', - new_name='solution', - ), - ] diff --git a/core/migrations/0010_auto_20170710_1604.py b/core/migrations/0010_auto_20170710_1604.py deleted file mode 100644 index ab702ede9c84a59e0762885ed0aaef9d40d5ae2d..0000000000000000000000000000000000000000 --- a/core/migrations/0010_auto_20170710_1604.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-10 16:04 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0009_auto_20170710_1308'), - ] - - operations = [ - migrations.CreateModel( - name='Test', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=30, unique=True)), - ('label', models.CharField(max_length=50, unique=True)), - ('annotation', models.TextField()), - ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tests', to='core.Submission')), - ], - options={ - 'verbose_name': 'Test', - 'verbose_name_plural': 'Tests', - }, - ), - migrations.AlterUniqueTogether( - name='test', - unique_together=set([('submission', 'name')]), - ), - ] diff --git a/core/migrations/0011_auto_20170710_1610.py b/core/migrations/0011_auto_20170710_1610.py deleted file mode 100644 index 7bf4689a3ab7df1d1112e9930660aedbc85da745..0000000000000000000000000000000000000000 --- a/core/migrations/0011_auto_20170710_1610.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-10 16:10 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0010_auto_20170710_1604'), - ] - - operations = [ - migrations.AlterField( - model_name='test', - name='label', - field=models.CharField(max_length=50), - ), - migrations.AlterField( - model_name='test', - name='name', - field=models.CharField(max_length=30), - ), - ] diff --git a/core/migrations/0012_auto_20170711_1104.py b/core/migrations/0012_auto_20170711_1104.py deleted file mode 100644 index 9cc1976430b11665b40073f68b976860fd163598..0000000000000000000000000000000000000000 --- a/core/migrations/0012_auto_20170711_1104.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-11 11:04 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0011_auto_20170710_1610'), - ] - - operations = [ - migrations.CreateModel( - name='ExamType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('module_reference', models.CharField(max_length=50)), - ('total_score', models.PositiveIntegerField()), - ('pass_score', models.PositiveIntegerField()), - ('pass_only', models.BooleanField(default=False)), - ], - options={ - 'verbose_name': 'ExamType', - 'verbose_name_plural': 'ExamTypes', - }, - ), - migrations.AddField( - model_name='student', - name='exam', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='students', to='core.ExamType'), - ), - ] diff --git a/core/migrations/0013_auto_20170712_1643.py b/core/migrations/0013_auto_20170712_1643.py deleted file mode 100644 index bd526207077997edd6dd8b0d2277dd1537d96f66..0000000000000000000000000000000000000000 --- a/core/migrations/0013_auto_20170712_1643.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-12 16:43 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0012_auto_20170711_1104'), - ] - - operations = [ - migrations.AlterField( - model_name='examtype', - name='module_reference', - field=models.CharField(max_length=50, unique=True), - ), - migrations.AlterField( - model_name='student', - name='user', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0014_auto_20170712_1704.py b/core/migrations/0014_auto_20170712_1704.py deleted file mode 100644 index 65a9c943d2aa857d13e44a062bacf5b24629bd5b..0000000000000000000000000000000000000000 --- a/core/migrations/0014_auto_20170712_1704.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-12 17:04 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0013_auto_20170712_1643'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='of_tutor', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_list', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/migrations/0015_auto_20170713_1220.py b/core/migrations/0015_auto_20170713_1220.py deleted file mode 100644 index eb7230989fa12669bcd06131e0a720a5a9ba6666..0000000000000000000000000000000000000000 --- a/core/migrations/0015_auto_20170713_1220.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-07-13 12:20 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0014_auto_20170712_1704'), - ] - - operations = [ - migrations.AlterModelOptions( - name='submission', - options={'ordering': ('type__name',), 'verbose_name': 'Submission', 'verbose_name_plural': 'Submission Set'}, - ), - ] diff --git a/core/migrations/0016_auto_20170714_1634.py b/core/migrations/0016_auto_20170714_1634.py deleted file mode 100644 index 227a18a80fc0cbc9515d367fa32fcfe20a2555d3..0000000000000000000000000000000000000000 --- a/core/migrations/0016_auto_20170714_1634.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.3 on 2017-07-14 16:34 -from __future__ import unicode_literals - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0015_auto_20170713_1220'), - ] - - operations = [ - migrations.RemoveField( - model_name='submission', - name='pre_corrections', - ), - migrations.AlterField( - model_name='feedback', - name='of_reviewer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='reviewed_submissions', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='feedback', - name='of_tutor', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='feedback_list', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='student', - name='exam', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='students', to='core.ExamType'), - ), - migrations.AlterField( - model_name='submission', - name='type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='submissions', to='core.SubmissionType'), - ), - ] diff --git a/core/serializers.py b/core/serializers.py deleted file mode 100644 index 8ff9df315a2fe0893112916ef40eb5126d4d6c17..0000000000000000000000000000000000000000 --- a/core/serializers.py +++ /dev/null @@ -1,91 +0,0 @@ - -import hashlib - -from django.contrib.auth.models import User -from rest_framework import serializers - -from core.models import Feedback, Student, Submission, SubmissionType - - -class SubmissionTypeSerializer(serializers.ModelSerializer): - - def create(self, validated_data): - return SubmissionType(**validated_data) - - class Meta: - model = SubmissionType - exclude = ('slug',) - - -class CreateStudentSerializer(serializers.ModelSerializer): - - username = serializers.CharField(source='user.username') - email = serializers.CharField(source='user.email') - password = serializers.CharField(source='user.password') - - class Meta: - model = Student - fields = ('username', 'name', 'email', 'matrikel_no', 'password') - extra_kwargs = {'password': {'write_only': True}} - - def to_representation(self, obj): - return { - 'username' : obj.user.username, - 'name' : obj.name, - 'matrikel_no' : obj.matrikel_no, - } - - def create(self, validated_data): - user = User( - email=validated_data['email'], - username=validated_data['username'] - ) - user.set_password(validated_data['password']) - - return Student.objects.create( - name=validated_data['name'], - matrikel_no=validated_data['matrikel_no'], - user=user, - ) - - -class CreateSubmissionSerializer(serializers.ModelSerializer): - - type = serializers.SlugRelatedField( - queryset=SubmissionType.objects.all(), - slug_field='name' - ) - - student = serializers.SlugRelatedField( - queryset=User.objects.all(), - slug_field='username' - ) - - class Meta: - model = Submission - fields = ('type', 'text', 'pre_corrections', 'student') - - def create(self, validated_data): - validated_data['student'] = validated_data['student'].student - return Submission.objects.create(**validated_data) - - -class AnonymousFeedbackSerializer(serializers.ModelSerializer): - - def to_representation(self, obj): - return { - 'feedback' : obj.text, - 'score' : obj.score, - 'tutor' : obj.of_tutor.username, - 'student' : hashlib.sha256( - obj.of_submission.student.matrikel_no.encode() + - obj.of_submission.student.name.encode()).hexdigest(), - 'code' : obj.of_submission.text - } - - def create(self, validated_data): - return NotImplemented - - class Meta: - model = Feedback - fields = () diff --git a/core/static/css/custom.css b/core/static/css/custom.css deleted file mode 100644 index 8e2e7f1cd81a4773dae66f4408bf3a3e7640ccb9..0000000000000000000000000000000000000000 --- a/core/static/css/custom.css +++ /dev/null @@ -1,61 +0,0 @@ - -pre { - width: 100%; - white-space: -moz-pre-wrap; /* Mozilla, supported since 1999 */ - white-space: -pre-wrap; /* Opera */ - white-space: -o-pre-wrap; /* Opera */ - white-space: pre-wrap; /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */ - word-wrap: break-word; /* IE 5.5+ */ -} - -.card-block{ - padding: 0; -} - -.editor { - position: relative; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: auto; -} - -.editor-code { - height: 500px; -} - -.editor-pre { - height: 200px; -} - -.nopadding { - padding: 0 !important; -} - -.nopadding-right { - padding-right: 0 !important; -} - -.nomargin { - margin: 0 !important; -} - -table.dataTable { - clear:both; - margin-top: 0 !important; - margin-bottom: 0 !important; - padding: 0 !important; - border-collapse:separate !important -} - -.col-sm-12 { - padding: 0 !important; -} - -.table td.fit, -.table th.fit { - white-space: nowrap; - width: 1%; -} - diff --git a/core/templates/base.html b/core/templates/base.html deleted file mode 100644 index 8ac759ae0f14736164e80a65bb7825eb79545a16..0000000000000000000000000000000000000000 --- a/core/templates/base.html +++ /dev/null @@ -1,79 +0,0 @@ -{% load staticfiles %} -{% load compress %} - -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="description" content=""> - <meta name="author" content=""> - - <title>Grady - {% block title %}Wellcome to correction hell!{% endblock %}</title> - - {# CSS includes #} - {% compress css %} - <link rel="stylesheet" href="{% static 'node_modules/datatables.net-bs4/css/dataTables.bootstrap4.css' %}"> - <link rel="stylesheet" href="{% static 'node_modules/bootstrap/dist/css/bootstrap.min.css' %}"> - <link rel="stylesheet" href="{% static 'css/custom.css' %}"> - {% endcompress %} - - {% compress js %} - {# Importing stuff for ACE editor #} - <script src="{% static 'node_modules/ace-editor-builds/src-min/ace.js' %}"></script> - <script src="{% static 'node_modules/ace-editor-builds/src-min/mode-c_cpp.js' %}"></script> - - {# Load other javascript #} - <script src="{% static 'node_modules/jquery/dist/jquery.min.js' %}"></script> - <script src="{% static 'node_modules/popper.js/dist/umd/popper.min.js' %}"></script> - <script src="{% static 'node_modules/bootstrap/dist/js/bootstrap.min.js' %}"></script> - - {# sortable table stuff #} - <script src="{% static 'node_modules/datatables.net/js/jquery.dataTables.js' %}"></script> - <script src="{% static 'node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js' %}"></script> - {% endcompress %} -</head> - -{# Navbar contaning: Brand - Title - User menu bar <---> (Username - Logout || Login form) #} -<nav class="navbar navbar-expand navbar-light bg-light"> - <a class="navbar-brand" href="{% url 'start' %}"> - <img src="{% static 'res/brand.png' %}" width="30" height="30" class="d-inline-block align-top" alt=""> - Grady - </a> - - <div class="navbar-nav mr-auto"> - {% block navbar %}Grady, Sir. Delbert Grady.{% endblock navbar %} - </div> - - {% if user.is_authenticated %} - <ul class="nav nav-pills"> - <li class="nav-item"><a class="btn mr-1 navbar-btn btn-link" href="{% url 'start' %}">{{ user.username }}</a></li> - <li class="nav-item"><a class="btn mr-1 navbar-btn btn-outline-primary" href="{% url 'logout' %}" role="button">Logout</a></li> - <li class="nav-item"><a class="btn mr-1 navbar-btn btn-outline-danger" href="https://gitlab.gwdg.de/j.michal/grady" target="_blank">Give Feedback</a></li> - </ul> - {% else %} - <form id="login_form" class="navbar-form form-inline" role="form" method="post" action="/login/"> - {% csrf_token %} - <div class="form-group mx-sm-1"> - <input type="text" class="form-control" name="username" value="" placeholder="Username" autofocus> - </div> - <div class="form-group mx-sm-1"> - <input type="password" class="form-control" name="password" value="" placeholder="Password"> - </div> - <div class="form-group mx-sm-1"> - <button type="submit" class="btn btn-primary">Login</button> - </div> - </form> - {% endif %} -</nav> - -<body> - <div class="container-fluid"> - {% block body_block %} - {% endblock %} - </div> - - {% block script_block %} - {% endblock script_block %} -</body> -</html> diff --git a/core/templates/core/component/feedback_badge.html b/core/templates/core/component/feedback_badge.html deleted file mode 100644 index 724f0ec9e605bc5b15f402036ebec2c9b649a2b7..0000000000000000000000000000000000000000 --- a/core/templates/core/component/feedback_badge.html +++ /dev/null @@ -1,9 +0,0 @@ -{% if feedback.status == feedback.EDITABLE %} - <span class="badge badge-info">{{feedback.get_status_display}}</span> -{% elif feedback.status == feedback.NEEDS_REVIEW %} - <span class="badge badge-primary">{{feedback.get_status_display}}</span> -{% elif feedback.status == feedback.ACCEPTED %} - <span class="badge badge-success">{{feedback.get_status_display}}</span> -{% elif feedback.status == feedback.OPEN %} - <span class="badge badge-warning">{{feedback.get_status_display}}</span> -{% endif %} diff --git a/core/templates/core/component/feedback_card.html b/core/templates/core/component/feedback_card.html deleted file mode 100644 index e5a8917d6f64e87ac5e51557ed5ed2c36c12fccb..0000000000000000000000000000000000000000 --- a/core/templates/core/component/feedback_card.html +++ /dev/null @@ -1,10 +0,0 @@ -<div class="card my-1"> - <a data-toggle="collapse" href="#collapse{{unique}}"> - <h5 class="card-header">{{ header }}</h5> - </a> - <div id="collapse{{unique}}" class="collapse {{expanded}}" role="tabpanel"> - <div class="card-block m-2"> - {{ content|safe }} - </div> - </div> -</div> diff --git a/core/templates/core/component/message_box.html b/core/templates/core/component/message_box.html deleted file mode 100644 index 8bef55250c2a2720e48117eadf43786da67c4b4d..0000000000000000000000000000000000000000 --- a/core/templates/core/component/message_box.html +++ /dev/null @@ -1,25 +0,0 @@ -{# This is where all the messages pop up #} -{% if messages or form.errors %} -<div class="row"> - <div class="col my-2"> - {% for message in messages %} - <div class="alert {{ message.tags }} alert-dismissible fade show" role="alert"> - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> - <span aria-hidden="true">×</span> - </button> - {{message}} - </div> - {% endfor %} - {% if form %} - {% for error in form.non_field_errors %} - <div class="alert alert-danger alert-dismissible fade show" role="alert"> - <button type="button" class="close" data-dismiss="alert" aria-label="Close"> - <span aria-hidden="true">×</span> - </button> - {{error}} - </div> - {% endfor %} - {% endif %} - </div> -</div> -{% endif %} diff --git a/core/templates/core/component/tests_editor.html b/core/templates/core/component/tests_editor.html deleted file mode 100644 index 362397783a8d19310265168dee86069754c1aa49..0000000000000000000000000000000000000000 --- a/core/templates/core/component/tests_editor.html +++ /dev/null @@ -1,27 +0,0 @@ -{# Custom feedback from the compiler #} -<div class="card my-1"> - <a data-toggle="collapse" href="#collapse4"> - <h5 class="card-header">Tester Output</h5> - </a> - <div id="collapse4" class="collapse hide" role="tabpanel"> - <div class="card-block m-2"> - <div id="tests_editor" class="editor editor-pre">{% for test in submission.tests.all %} -# {{test.name}} -{{test.annotation}} -RESULT: {{test.label}} -------------------------------------------------- -{% endfor %} - </div> - </div> - </div> - <script> - var editor_pre = ace.edit("tests_editor"); - editor_pre.setOptions({ - readOnly: true, - showGutter: false, - highlightActiveLine: false, - maxLines: Infinity, - }) - </script> -</div> - diff --git a/core/templates/core/feedback_form.html b/core/templates/core/feedback_form.html deleted file mode 100644 index 601aa89b6a881f939fc29b0aab08d994f2f4a283..0000000000000000000000000000000000000000 --- a/core/templates/core/feedback_form.html +++ /dev/null @@ -1,210 +0,0 @@ -{% extends "base.html" %} - -{% block navbar %} {{ grady_says }} {% endblock navbar %} - -{% block title %} Editing feedback {% endblock %} - -{% load staticfiles %} - -{% block body_block %} -<div class="row"> - <div class="col my-2 nopadding-right"> - - <div class="card mb-2"> - <div class="card-header form-inline pb-1"> - <h4 class="mr-2">{{feedback.of_submission.type.name}}</h4> - <a href="{% url 'download_submissions' feedback.of_submission.slug %}" class="btn btn-sm btn-outline-primary mb-1">Download</a> - </div> - <div class="card-block"> - <div id="student_text" class="editor editor-code"></div> - </div> - </div> - - {# Custom feedback from the compiler #} - <div class="card my-1"> - <a data-toggle="collapse" href="#collapse4"> - <h5 class="card-header">Custom Feedback</h5> - </a> - <div id="collapse4" class="collapse show" role="tabpanel"> - <div class="card-block m-2"> - <div id="tests_editor" class="editor editor-pre">{% for test in feedback.of_submission.tests.all %} -# {{test.name}} -{{test.annotation}} -RESULT: {{test.label}} -------------------------------------------------- - {% endfor %}</div> - </div> - </div> - </div> - - {# A sample solution #} - <div class="card my-1"> - <a data-toggle="collapse" href="#collapse5"> - <h5 class="card-header">Sample Solution</h5> - </a> - <div id="collapse5" class="collapse show" role="tabpanel"> - <div class="card-block m-2"> - <div id="solution" class="editor editor-code">{{feedback.of_submission.type.solution}}</div> - </div> - </div> - </div> - - {% include "core/component/feedback_card.html" with unique="1" header="Description" content=feedback.of_submission.type.description expanded="hide" %} - - <div class="my-2"> - <button type="button" id="collapseAllOpen" class="btn btn-secondary">Open All</button> - <button type="button" id="collapseAllClose" class="btn btn-secondary">Close All</button> - </div> - </div> - - <div class="col my-2"> - <div class="row-auto mb-2"> - <div class="card"> - <h4 class="card-header">Please provide your feedback</h4> - <div class="card-block"> - <div class="editor editor-code" id="tutor_text" autofocus></div> - </div> - </div> - </div> - - <div class="row-auto"> - <form action="{% url 'FeedbackEdit' feedback.slug %}" method="post" id="form1"> - {% csrf_token %} - <div hidden> {{ form.text }} </div> - <div class="form-inline"> - - {# Score field #} - <div class="input-group col-5 nopadding mr-1 mb-2"> - <span class="input-group-addon">Score:</span> - <input - class="form-control" - id="id_score" - min="0" max="{{ feedback.of_submission.type.full_score }}" - name="score" - type="number" - value="{{ form.score.value }}" - required - {% if feedback.status == feedback.ACCEPTED %}readonly{% endif %}> - <span class="input-group-btn"> - <button id="assign_full_score" class="btn btn-secondary" type="button"><code>/{{ feedback.of_submission.type.full_score }}</code></button> - </span> - </div> - - {# status select #} - {% with form.fields.status as status %} - <div class="form-group mr-2 mb-2"> - <select class="custom-select" id="id_status" name="status"> - {% for val, name in status.choices %} - <option value="{{val}}" {% if val == feedback.status %}selected{% endif %}>{{name}}</option> - {% endfor %} - </select> - </div> - {% endwith %} - - <div> - {# Beware! compares status and origin #} - <button type="submit" form="form1" class="btn btn-outline-success mb-2" name="update" value="Save">Save</button> - <button type="submit" form="form1" class="btn btn-outline-success mb-2" name="update" value="Submit">Save and return</button> - - {% if feedback.status == feedback.NEEDS_REVIEW or feedback.status == feedback.EDITABLE %} - <button type="submit" onclick="set_accepted();" form="form1" class="btn btn-outline-success mb-2" name="update" value="Next">Accept, Save and Next</button> - {% endif %} - - {% if feedback.origin != feedback.MANUAL %} - <a href="{% url 'FeedbackDelete' feedback.slug %}" class="btn btn-outline-danger mb-2" name="delete" value="Delete">Delete auto feedback</a> - {% endif %} - - {% if feedback.status == feedback.ACCEPTED %} - <button class="btn btn-secondary mr-1 mb-2" value="Submit" disabled>View is read only</button> - {% endif %} - </div> - </div> - </form> - </div> - {# This is where all the messages pop up #} - {% include "core/component/message_box.html" %} - </div> -</div> -</div> -</div> - -{% endblock %} - -{% block script_block %} -<script> - - function set_accepted() { - $('#id_status')[0].value = {{feedback.ACCEPTED}}; - } - - $('#collapseAllOpen').click(function(){ - $('.collapse').collapse('show'); - }); - - $('#collapseAllClose').click(function(){ - $('.collapse').collapse('hide'); - }); - - {% if feedback.status != feedback.ACCEPTED %} - $('#assign_full_score').click(function(){ - $('#id_score')[0].value = {{ feedback.of_submission.type.full_score }}; - }) - {% endif %} - - // we need this one for the compiler erros readonly - var editor_pre = ace.edit("tests_editor"); - editor_pre.setOptions({ - readOnly: true, - showGutter: false, - highlightActiveLine: false, - maxLines: Infinity, - }) - - // we need this one for the sample solution readonly - var editor_solution = ace.edit("solution"); - editor_solution.getSession().setMode("ace/mode/c_cpp"); - editor_solution.setOptions({ - readOnly: true, - showGutter: false, - highlightActiveLine: false, - maxLines: Infinity, - }) - - // we need this one for the student readonly - var editor_student = ace.edit("student_text"); - editor_student.setValue(`{{feedback.of_submission.text|safe|escapejs}}`, -1); - editor_student.getSession().setMode("ace/mode/c_cpp"); - editor_student.setOptions({ - readOnly: true, - maxLines: Infinity, - }) - - // we need this one for the tutor - var editor_tutor = ace.edit("tutor_text"); - var textarea = $('textarea[id="id_text"]'); - editor_tutor.focus(); - editor_tutor.setValue(`{{feedback.text|safe|escapejs}}`, -1); - editor_tutor.getSession().setUseWrapMode(true) - editor_tutor.getSession().on("change", function () { - textarea.val(editor_tutor.getSession().getValue()); - }); - - editor_tutor.setOptions({'minLines': editor_student.getSession().getLength()}) - editor_tutor.setOptions({'maxLines': editor_student.getSession().getLength()}) - - editor_tutor.getSelection().on('changeCursor', function() { - cursor_pos_tutor = editor_tutor.getCursorPosition(); - cursor_pos_tutor.column = 0; - editor_student.getSelection().moveCursorToPosition(cursor_pos_tutor); - editor_student.getSelection().clearSelection(); - }) - - {% if feedback.status == feedback.ACCEPTED %} - editor_tutor.setOptions({ - readOnly: true, - }) - {% endif %} - -</script> -{% endblock script_block %} - diff --git a/core/templates/core/index.html b/core/templates/core/index.html deleted file mode 100644 index 33df883846dcb4182cd4dbb2706f19ec1ae39847..0000000000000000000000000000000000000000 --- a/core/templates/core/index.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'base.html' %} - -{% load staticfiles %} - -{% block nav_title %} Grady, Sir. Delbert Grady. {% endblock nav_title %} - -{% block body_block %} -<div class="row justify-content-center my-2"> - <div class="col-6"> - - {# This is where all the messages pop up #} - {% include "core/component/message_box.html" %} - - </div> -</div> - -{% endblock %} diff --git a/core/templates/core/r/feedback_list.html b/core/templates/core/r/feedback_list.html deleted file mode 100644 index d5962d95766d4cf3d2a18b41c7800aabd34c9fa3..0000000000000000000000000000000000000000 --- a/core/templates/core/r/feedback_list.html +++ /dev/null @@ -1,42 +0,0 @@ -<div class="card mb-2"> - <a data-toggle="collapse" href="#collapse{{unique}}"> - <h5 class="card-header">{{header}}</h5> - </a> - <div id="collapse{{unique}}" class="collapse {{expanded}}" role="tabpanel"> - <div class="card-block"> - <table id="list-id-{{unique}}" class="table nomargin"> - <thead> - <tr> - <th>Status</th> - <th>Submission Type</th> - <th>Student</th> - <th>Score</th> - <th>Auto feedback</th> - <th>Modified</th> - <th></th> - </tr> - </thead> - <tbody> - {% for feedback in feedback_list %} - <tr> - <td class="align-middle"> - {% include "core/component/feedback_badge.html" %} - </td> - <td class="align-middle"> {{ feedback.of_submission.type }} </td> - <td class="align-middle"> {{ feedback.of_submission.student }} </td> - <td class="align-middle"> <code> {{ feedback.score }} / {{ feedback.of_submission.type.full_score }} </code> </td> - <td class="align-middle"> {{ feedback.get_origin_display }} </td> - <td class="align-middle"> -- </td> - <td class="align-middle"> - {% if not feedback.origin == feedback.WAS_EMPTY %} - <a href="{% url 'FeedbackEdit' feedback.slug %}" class="btn btn-outline-primary mb-1" name="edit" value="View">View</a> - <a href="{% url 'FeedbackDelete' feedback.slug %}" class="btn btn-outline-danger mb-1" name="delete" value="Delete">Delete</a> - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - </div> -</div> diff --git a/core/templates/core/r/progress_card.html b/core/templates/core/r/progress_card.html deleted file mode 100644 index 99b20f301e42d1a07610106083903d1accb09ecc..0000000000000000000000000000000000000000 --- a/core/templates/core/r/progress_card.html +++ /dev/null @@ -1,24 +0,0 @@ -{# This just gives an overview about what has been done already #} -<div class="card mb-2"> - <h5 class="card-header">Progress</h5> - <table class="table nomargin"> - <thead> - <th>Name</th> - <th>Progress</th> - <th></th> - </thead> - <tbody> - {% for submission_type in submission_type_list %} - <tr> - <td class="align-middle">{{ submission_type }}</td> - <td class="align-middle" width="30%"> - <div class="progress"> - <div class="progress-bar" role="progressbar" style="width: {{submission_type.percentage}}%;"></div> - </div> - </td> - <td class="align-middle fit"><code>{{ submission_type.feedback_count }} / {{submission_type.submission_count}}</code></td> - </tr> - {% endfor %} - </tbody> - </table> -</div> diff --git a/core/templates/core/r/reviewer_base.html b/core/templates/core/r/reviewer_base.html deleted file mode 100644 index c79f575f6e3321ba897604d6c1dd143394a65e58..0000000000000000000000000000000000000000 --- a/core/templates/core/r/reviewer_base.html +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "base.html" %} - -{% load staticfiles %} - -{% block navbar %} -<a class="nav-item nav-link" href="{% url 'start' %}">Feedback</a> -<a class="nav-item nav-link" href="{% url 'ReviewerSubmissionListView' %}">Submissions</a> -<a class="nav-item nav-link" href="{% url 'ReviewerStudentListView' %}">Students</a> -<div class="nav-item dropdown"> - <a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - Export - </a> - <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink"> - <a class="dropdown-item" href="{% url 'export' %}">Download Results CSV</a> - </div> -</div> -{% endblock navbar %} - -{% block body_block %} -<div class="row my-3"> - <div class="col-3"> - {% block sidebar %} - {# This just gives an overview about what has been done already #} - {% include "core/r/progress_card.html" %} - - {# Only a list of tutors. Currently no controls available #} - {% include "core/r/tutor_list_card.html" %} - {% endblock sidebar %} - </div> - - <div class="col-9"> - {% block main %} - - {% endblock main %} - </div> -</div> - -{% endblock body_block %} - -{% block script_block %} -<script> - $(document).ready(function() { - $('[id^=list-id-]').DataTable({ - "paging": false, - "info": false, - "searching": false, - "stateSave": true, - "order": [[ 0, 'desc' ], [ 2, 'desc' ]], - "columnDefs": [ - { "orderable": false, "targets": -1 }, - ] - }); - }); -</script> -{% endblock script_block %} diff --git a/core/templates/core/r/reviewer_startpage.html b/core/templates/core/r/reviewer_startpage.html deleted file mode 100644 index 3fdb2c1f378ee45949b1899d6615d355c0812b84..0000000000000000000000000000000000000000 --- a/core/templates/core/r/reviewer_startpage.html +++ /dev/null @@ -1,54 +0,0 @@ -{% extends 'core/r/reviewer_base.html' %} - -{% load staticfiles %} - -{% block main %} -<div class="card mb-2"> - {% if feedback_list_manual|length == 0 %} - <h5 class="card-header">There is no feedback, yet. Maybe you have to kick some ass?</h5> - {% elif feedback_list_manual|length == 1 %} - <h5 class="card-header">Well, one is better than nothing</h5> - {% else %} - <h5 class="card-header">So far {{feedback_list_manual|length}} contributions were provided</h5> - {% endif %} - <div class="card-block"> - <table id="list-id-0" class="table nomargin"> - <thead> - <tr> - <th>Status</th> - <th>Submission Type</th> - <th>Student</th> - <th>Score</th> - <th>Tutor</th> - <th>Modified</th> - <th></th> - </tr> - </thead> - <tbody> - {% for feedback in feedback_list_manual %} - <tr> - <td class="align-middle fit"> - {% include "core/component/feedback_badge.html" %} - </td> - <td class="align-middle"> {{ feedback.of_submission.type }} </td> - <td class="align-middle"> {{ feedback.of_submission.student }} </td> - <td class="align-middle"> <code> {{ feedback.score }} / {{ feedback.of_submission.type.full_score }} </code> </td> - <td class="align-middle"> {{ feedback.of_tutor}} </td> - <td class="align-middle"> {{ feedback.modified | date:"m/d/y H:i"}} </td> - <td class="align-middle"> - <a href="{% url 'FeedbackEdit' feedback.slug %}" class="btn btn-outline-primary mb-1" name="edit" value="View">View</a> - <a href="{% url 'FeedbackDelete' feedback.slug %}" class="btn btn-outline-danger mb-1" name="delete" value="Delete">Delete</a> - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> -</div> - -{# This is card for empty feedback for the sake of completeness #} -{% include "core/r/feedback_list.html" with expanded="show" header="Did not compile feedback" unique="2" feedback_list=feedback_list_did_not_compile %} -{% include "core/r/feedback_list.html" with expanded="show" header="Could not link feedback" unique="3" feedback_list=feedback_list_could_not_link %} -{% include "core/r/feedback_list.html" with expanded="hide" header="Empty feedback" unique="1" feedback_list=feedback_list_empty %} - -{% endblock main %} diff --git a/core/templates/core/r/single_submission.html b/core/templates/core/r/single_submission.html deleted file mode 100644 index 59f26832868b3da5e9b84b151cd713c043dabea7..0000000000000000000000000000000000000000 --- a/core/templates/core/r/single_submission.html +++ /dev/null @@ -1,89 +0,0 @@ -{% extends "core/r/reviewer_base.html" %} - -{% block body_block %} - -{% with submission.feedback as feedback %} -<div class="row justify-content-center"> - <div class="col-3 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header"> - Student Submission - </div> - <ul class="list-group list-group-flush"> - <li class="list-group-item"><strong class="mr-2">Submission Type: </strong> {{ submission.type }} </li> - <li class="list-group-item"><strong class="mr-2">Student: </strong> {{ submission.student }}</li> - <li class="list-group-item"> - <strong class="mr-2">Status: </strong> {% include "core/component/feedback_badge.html" %} - <span class="badge badge-warning ml-2">Only visible to reviewer</span> - </li> - <li class="list-group-item"> - <strong class="mr-2">Tutor: </strong> {{ feedback.of_tutor }} - <span class="badge badge-warning ml-2">Only visible to reviewer</span> - </li> - <li class="list-group-item"><strong class="mr-2">Score: </strong> - {% if feedback %} - <code> {{ feedback.score }} / {{submission.type.full_score}} </code> - <span class="badge badge-warning ml-2">Only visible to reviewer</span> - {% else %} - <span class="badge badge-danger">No Feedback</span> - {% endif %} - </li> - </ul> - </div> - <div class="card-footer"> - <a href="{% url 'create_feedback_for_submission' submission.slug %}" class="btn btn-success"> - {% if feedback %} - Edit Feedback - {% else %} - Create Feedback - {% endif %} - </a> - <button class="btn btn-outline-success" onclick="window.history.go(-1); return false;">Back</button> - </div> - </div> - </div> - - <div class="col-4 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header">Student submission</div> - <div class="editor-code" id="textarea_submission">{{submission.text}}</div> - </div> - </div> - {% include "core/component/tests_editor.html" %} - </div> - - {% if feedback %} - <div class="col-4 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header">Our feedback - {% if is_reviewer %} - <span class="badge badge-warning ml-2">Only visible to reviewer</span> - {% endif %} - </div> - <div class="editor-code" id="textarea_feedback">{{ feedback.text }}</div> - </div> - </div> - </div> - <script> - var feedback_editor = ace.edit("textarea_feedback"); - feedback_editor.setOptions({ - readOnly: true, - }) - </script> - {% endif %} -</div> -{% endwith %} -{% endblock body_block %} - - -{% block script_block %} -<script> - var submission_editor = ace.edit("textarea_submission"); - submission_editor.setOptions({ - readOnly: true, - }) -</script> -{% endblock script_block %} diff --git a/core/templates/core/r/student_list.html b/core/templates/core/r/student_list.html deleted file mode 100644 index 57f433f05720ecc6e29f96ea93772ad86635c508..0000000000000000000000000000000000000000 --- a/core/templates/core/r/student_list.html +++ /dev/null @@ -1,59 +0,0 @@ -{% extends 'core/r/reviewer_base.html' %} - -{% load staticfiles %} - -{% block main %} - -<div class="card"> - <h5 class="card-header">Student Overview</h5> - <div class="card-block"> - <table id="list-id-submission_list" class="table nomargin"> - <thead class="rotate"> - <tr class="high"> - <th>Name</th> - <th>Username</th> - <th>Module</th> - {% for submission_type in submission_type_list %} - <th><font size="1">{{submission_type.name}}</font></th> - {% endfor %} - <th>Total score</th> - <th>Done</th> - </tr> - </thead> - <tbody> - {% for student in student_list %} - <tr> - <td class="fit">{{student.name}}</td> - <td>{{student.user.username}}</td> - <td>{{student.exam}}</td> - {% for sub in student.submissions.all %} - <td>{% if sub.feedback %} - <a href="{% url 'ReviewerSubmissionView' sub.slug %}" role="button" class="btn-link btn-sm"><code>{{sub.feedback.score}} / {{sub.type.full_score}}</code></a> - {% else %} - <a href="{% url 'ReviewerSubmissionView' sub.slug %}" role="button" class="btn btn-outline-primary btn-sm">View</a> - {% endif %} </td> - {% endfor %} - <td><code>{{student.overall_score}}</code></td> - <td>{% if student.done %}<span class="badge badge-success">yes</span>{% else %}<span class="badge badge-danger">no</span>{% endif %}</td> - </tr> - {% endfor %} - </tbody> - </table> - </div> -</div> - -{% endblock main %} - -{% block script_block %} -<script> - $(document).ready(function() { - $('[id^=list-id-]').DataTable({ - "paging": false, - "info": false, - "searching": false, - "stateSave": true, - "order": [[ 0, 'desc' ]], - }); - }); -</script> -{% endblock script_block %} diff --git a/core/templates/core/r/student_submission_list.html b/core/templates/core/r/student_submission_list.html deleted file mode 100644 index 484bdd8e06323d57ae8256cd09ad8ef8f53fe145..0000000000000000000000000000000000000000 --- a/core/templates/core/r/student_submission_list.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends 'core/r/reviewer_base.html' %} - -{% load staticfiles %} - -{% block main %} - -<div class="card"> - <h5 class="card-header">All student submissions</h5> - <div class="card-block"> - <table id="list-id-submission_list" class="table nomargin"> - <thead> - <tr> - <th></th> - <th>Task</th> - <th>Student</th> - <th>Score</th> - <th>Tutor</th> - <th></th> - </tr> - </thead> - <tbody> - {% for submission in submission_list %} - <tr> - <td class="align-middle fit"> <a href="{% url 'ReviewerSubmissionView' submission.slug %}" class="btn btn-outline-primary mb-1" name="edit" value="View">View submission</a></td> - <td class="align-middle"> {{ submission.type }} </td> - <td class="align-middle"> {{ submission.student }} </td> - <td class="align-middle fit"> - {% if submission.feedback %} - <code> {{ submission.feedback.score }} / {{ submission.type.full_score }} </code> - {% else %} - <code> no feedback </code> - {% endif %} - </td> - <td class="align-middle"> - {% if submission.feedback %} - {{submission.feedback.of_tutor}} - {% endif %} - </td> - <td class="align-middle fit"> - {% if submission.feedback %} - {% if submission.feedback.origin == submission.feedback.WAS_EMPTY %} - <button type="button" class="btn btn-secondary" disabled>was empty</button> - {% else %} - <a href="{% url 'FeedbackEdit' submission.feedback.slug %}" class="btn btn-outline-primary" name="edit" value="View">Edit Feedback</a> - <a href="{% url 'FeedbackDelete' submission.feedback.slug %}" class="btn btn-outline-danger" name="delete" value="Delete">Delete Feedback</a> - {% endif %} - {% else %} - <a href="{% url 'create_feedback_for_submission' submission.slug %}" class="btn btn-outline-success"> Create Feedback </a> - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> -</div> - -{% endblock main %} diff --git a/core/templates/core/r/tutor_list_card.html b/core/templates/core/r/tutor_list_card.html deleted file mode 100644 index 455927dc5cb645f7150f0bca91d4a60e9d3b6b0e..0000000000000000000000000000000000000000 --- a/core/templates/core/r/tutor_list_card.html +++ /dev/null @@ -1,19 +0,0 @@ -<div class="card mb-2"> - <h5 class="card-header">Tutor overview</h5> - <div class="card-block"> - <table class="table nomargin"> - <thead> - <th>Tutor</th> - <th># of feedbacks</th> - </thead> - {% for tutor in tutor_list %} - <tbody> - <tr> - <td>{{tutor.username}}</td> - <td><code>{{tutor.feedback_list__count}}</code></td> - </tr> - </tbody> - {% endfor %} - </table> - </div> -</div> diff --git a/core/templates/core/s/single_submission.html b/core/templates/core/s/single_submission.html deleted file mode 100644 index cf08272e7c32364a1e96e5c3a246bd59ba0b48d7..0000000000000000000000000000000000000000 --- a/core/templates/core/s/single_submission.html +++ /dev/null @@ -1,74 +0,0 @@ -{% extends "base.html" %} - -{% block nav_title %} Student Exam View {% endblock nav_title %} - -{% block body_block %} - -{% with submission.feedback as feedback %} -<div class="row justify-content-center"> - <div class="col-3 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header"> - Student Submission - </div> - <ul class="list-group list-group-flush"> - <li class="list-group-item"><strong class="mr-2">Submission Type: </strong> {{ submission.type }} </li> - <li class="list-group-item"><strong class="mr-2">Student: </strong> {{ submission.student }}</li> - <li class="list-group-item"><strong class="mr-2">Score: </strong> - {% if feedback and feedback.status == feedback.ACCEPTED %} - <code> {{ feedback.score }} / {{submission.type.full_score}} </code> - {% else %} - <span class="badge badge-danger">No Feedback</span> - {% endif %} - </li> - </ul> - </div> - <div class="card-footer"> - <a href="{% url 'start' %}" class="btn btn-success">Back</a> - </div> - </div> - </div> - - <div class="col-4 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header">Your submission</div> - <div class="editor-code" id="textarea_submission">{{submission.text}}</div> - </div> - </div> - {% include "core/component/tests_editor.html" %} - </div> - - {% if feedback %} - {% if feedback.status == feedback.ACCEPTED %} - <div class="col-4 my-4"> - <div class="card"> - <div class="card-block"> - <div class="card-header">Our feedback - </div> - <div class="editor-code" id="textarea_feedback">{{ feedback.text }}</div> - </div> - </div> - </div> - <script> - var feedback_editor = ace.edit("textarea_feedback"); - feedback_editor.setOptions({ - readOnly: true, - }) - </script> - {% endif %} - {% endif %} -</div> -{% endwith %} -{% endblock body_block %} - - -{% block script_block %} -<script> - var submission_editor = ace.edit("textarea_submission"); - submission_editor.setOptions({ - readOnly: true, - }) -</script> -{% endblock script_block %} diff --git a/core/templates/core/s/student_startpage.html b/core/templates/core/s/student_startpage.html deleted file mode 100644 index cd016dd7f5b03e445b895b4b2149f082118e580c..0000000000000000000000000000000000000000 --- a/core/templates/core/s/student_startpage.html +++ /dev/null @@ -1,48 +0,0 @@ -{% extends 'base.html' %} - -{% load staticfiles %} - -{% block navbar %} Student Exam View {% endblock navbar %} - -{% block body_block %} -<div class="row justify-content-center"> - <div class="col-6"> - <div class="row my-3"> - <h2>Submissions of {{ student.name }}</h2> - </div> - - <div class="row my-2"> - <table class="table"> - <thead> - <th></th> - <th>Submission Type</th> - <th>Score</th> - <th></th> - </thead> - <tbody> - {% for submission in student.submissions.all %} - <tr class="align-middle"> - <td class="align-middle"> - {% if submission.seen_by_student %} - <span class="badge badge-success">Seen</span> - {% endif %} - </td> - <td class="align-middle">{{ submission.type }}</td> - <td class="align-middle"> - {% with submission.feedback as feedback %} - {% if feedback and feedback.status == feedback.ACCEPTED %} - <code> {{ feedback.score }} / {{submission.type.full_score}} </code> - {% else %} - <span class="badge badge-danger">No Feedback</span> - {% endif %} - {% endwith %} - </td> - <td class="align-middle"><a class="btn btn-primary" href="{% url 'StudentSubmissionView' submission.slug %}">View</a></td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - </div> -</div> -{% endblock body_block %} diff --git a/core/templates/core/t/tutor_startpage.html b/core/templates/core/t/tutor_startpage.html deleted file mode 100644 index 52836ebf0bb4bb65d215a602108ca300b513f097..0000000000000000000000000000000000000000 --- a/core/templates/core/t/tutor_startpage.html +++ /dev/null @@ -1,130 +0,0 @@ -{% extends 'base.html' %} - -{% load staticfiles %} - -{% block navbar %} Ready for an exam, commander? {% endblock navbar %} - -{% block body_block %} - -<div class="row justify-content-center my-3"> - <div class="col-5 nopadding"> - - {# This is a control panel where new work can be requested #} - <div class="card mb-2"> - <h4 class="card-header">Overview</h4> - <table class="table nomargin"> - <thead> - <th></th> - <th>Name</th> - <th>Progress</th> - <th></th> - </thead> - <tbody> - {% for submission_type in submission_type_list %} - <tr> - <td class="align-middle"><a role="button" class="btn btn-secondary {% if submission_type.percentage == 100 %}disabled{% endif %}" href="{% url 'CreateFeedbackForType' submission_type.slug %}">Get</a></td> - <td class="align-middle fit">{{ submission_type }}</td> - <td class="align-middle" width="70%"> - <div class="progress"> - <div class="progress-bar" role="progressbar" style="width: {{submission_type.percentage}}%;"></div> - </div> - </td> - <td class="align-middle fit"><code>{{ submission_type.feedback_count }} / {{submission_type.submission_count}}</code></td> - </tr> - {% endfor %} - </tbody> - </table> - <table class="table nomargin"> - <tbody> - <tr> - <td class="fit"><strong>Your contribution:</strong></td> - <td colspan="6"><code>{% if tutor.feedback_list.all|length > 0 %} {{tutor.feedback_list.all|length}} {% else %} None. Sad. {% endif %}</code></td> - </tr> - </tbody> - </table> - <div class="card-footer text-muted"> - <a role="button" class="btn btn-outline-danger" href="{% url 'CreateFeedback' %}">Just give me anything</a> - </div> - </div> - - {# Open feedback will be displayed here #} - {% if feedback_open_list %} - <div class="card mb-2"> - <h4 class="card-header">Open Feedback</h4> - <table class="table nomargin"> - <thead> - <th>Task</th> - <th>Tutor</th> - <th></th> - </thead> - <tbody> - {% for feedback in feedback_open_list %} - <tr> - <td class="align-middle"> {{ feedback.of_submission.type }} </td> - <td class="align-middle"> {{ feedback.of_tutor }} </td> - <td class="align-middle"><a class="btn btn-secondary" href="{% url 'FeedbackEdit' feedback.slug %}"> Assign </a></td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - {% endif %} - - {# This is where all the messages pop up #} - {% include "core/component/message_box.html" %} - - </div> - <div class="col-6"> - {# The big table where the tutor can see what s/he actually did #} - <div class="row-auto nomargin justify-content-center"> - <table id="list-id-tutoren" class="table"> - <thead> - <tr> - <th>Status</th> - <th>Submission Type</th> - <th>Score</th> - <th>Modified</th> - <th></th> - </tr> - </thead> - <tbody> - {% for feedback in tutor.feedback_list.all %} - <tr> - <td> - {% include "core/component/feedback_badge.html" %} - </td> - <td> {{ feedback.of_submission.type }} </td> - <td> <code> {{ feedback.score }} / {{feedback.of_submission.type.full_score}} </code> </td> - <td> {{ feedback.modified | date:"H:i"}} </td> - <td> - {% if feedback.status == feedback.ACCEPTED %} - <a class="btn btn-secondary" href="{% url 'FeedbackEdit' feedback.slug %}"> View </a> - {% else %} - <a class="btn btn-primary" href="{% url 'FeedbackEdit' feedback.slug %}"> Edit </a> - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> - </table> - </div> - </div> -</div> -{% endblock body_block %} - -{% block script_block %} -<script> - $(document).ready(function() { - $('#list-id-tutoren').DataTable({ - "paging": false, - "info": false, - "searching": false, - "stateSave": true, - "order": [[ 0, 'desc' ], [ 3, 'desc' ]], - "columnDefs": [ - { "orderable": false, "targets": -1 }, - ] - }); - }); -</script> -{% endblock script_block %} diff --git a/core/urls.py b/core/urls.py deleted file mode 100644 index b79a568e167b1b441c76339261ed68171ec56176..0000000000000000000000000000000000000000 --- a/core/urls.py +++ /dev/null @@ -1,28 +0,0 @@ -from django.conf.urls import url -from django.contrib.staticfiles.urls import staticfiles_urlpatterns - -from core import views - -urlpatterns = [ - url(r'^$', views.IndexView.as_view(), name='index'), - url(r'^login/$', views.Login.as_view(), name='login'), - url(r'^logout/$', views.Logout.as_view(), name='logout'), - url(r'^start/$', views.user_home, name='start'), - - url(r'^feedback/create/$', views.create_feedback, name='CreateFeedback'), - url(r'^feedback/create/(?P<type_slug>\w+)/$', views.create_feedback, name='CreateFeedbackForType'), - url(r'^feedback/edit/(?P<feedback_slug>\w+)/$', views.FeedbackEdit.as_view(), name='FeedbackEdit'), - url(r'^feedback/delete/(?P<feedback_slug>\w+)/$', views.delete_feedback, name='FeedbackDelete'), - - url(r'^r/student/list/$', views.ReviewerStudentListView.as_view(), name='ReviewerStudentListView'), - url(r'^r/submission/list/$', views.ReviewerSubmissionListView.as_view(), name='ReviewerSubmissionListView'), - url(r'^r/submission/view/(?P<slug>\w+)/$', views.ReviewerSubmissionView.as_view(), name='ReviewerSubmissionView'), - url(r'^r/submission/create-feedback-for/(?P<slug>\w+)/$', views.create_feedback_for_submission, name='create_feedback_for_submission'), - url(r'^r/submission/download/(?P<slug>\w+)/$', views.download_submissions, name='download_submissions'), - - url(r'^s/submission/view/(?P<slug>\w+)/$', views.StudentSubmissionView.as_view(), name='StudentSubmissionView'), - - url(r'^csv/$', views.export_csv, name='export') -] - -urlpatterns += staticfiles_urlpatterns() diff --git a/core/views/__init__.py b/core/views/__init__.py deleted file mode 100644 index 67868d83114fb61ae463b7c2cd5b9bb0127f5bb1..0000000000000000000000000000000000000000 --- a/core/views/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .login import * -from .feedback import * -from .generics import * - -from .submission import * -from .user_startpages import * -from .index import * -from .export_csv import * - diff --git a/core/views/export_csv.py b/core/views/export_csv.py deleted file mode 100644 index 1e1a7fdd12d212085b0f36a0bef223019bdd2106..0000000000000000000000000000000000000000 --- a/core/views/export_csv.py +++ /dev/null @@ -1,28 +0,0 @@ -import csv - -from django.http import HttpResponse - -from core.custom_annotations import group_required -from core.models import Student, SubmissionType - - -@group_required('Reviewers') -def export_csv(request): - # Create the HttpResponse object with the appropriate CSV header. - response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename="grady_results.csv"' - - writer = csv.writer(response) - writer.writerow(['Matrikel', 'Username', 'Name', 'Sum'] + - [s.name for s in SubmissionType.objects.all().order_by('name')]) - - for student in Student.get_overall_score_annotated_submission_list(): - writer.writerow([ - student.matrikel_no, - student.user.username, - student.name, - student.overall_score, - *student.score_per_submission().values() - ]) - - return response diff --git a/core/views/feedback.py b/core/views/feedback.py deleted file mode 100644 index db95a26d8457c2286f871350787b1fa5846f4b9b..0000000000000000000000000000000000000000 --- a/core/views/feedback.py +++ /dev/null @@ -1,134 +0,0 @@ -from random import choice - -from django.contrib import messages -from django.http import Http404, HttpResponse, HttpResponseRedirect -from django.urls import reverse -from django.utils.decorators import method_decorator -from django.views.generic.edit import UpdateView - -from core.custom_annotations import group_required, in_groups -from core.forms import FeedbackForm -from core.grady_speak import grady_says -from core.models import Feedback, Submission, SubmissionType - - -@group_required('Tutors') -def create_feedback(request, type_slug=None): - # assign does nothing if tutor has unfinished feedback - assigned = Submission.assign_tutor(request.user, type_slug) - feedback = Feedback.tutor_unfinished_feedback(request.user) - if not feedback: - if type_slug: - messages.info(request, "No more submissions of type '%s' available." % - SubmissionType.objects.get(slug=type_slug)) - else: - messages.success( - request, "Well done! There is no more work to do.") - return HttpResponseRedirect(reverse('start')) - elif not assigned: - messages.info( - request, "You have got unfinished business. Please finish this task first.") - return HttpResponseRedirect(reverse('FeedbackEdit', args=(feedback.slug,))) - - -@group_required('Reviewers') -def create_feedback_for_submission(request, slug): - - submission = Submission.objects.get(slug=slug) - - if not hasattr(submission, 'feedback'): - submission.feedback = Feedback() - - submission.feedback.of_reviewer = request.user - submission.feedback.of_tutor = request.user - submission.feedback.of_submission = submission - - submission.feedback.save() - submission.save() - - return HttpResponseRedirect(reverse('FeedbackEdit', args=(submission.feedback.slug,))) - - -@group_required('Reviewers') -def delete_feedback(request, feedback_slug): - """ Hook to ensure object is owned by request.user. """ - instance = Feedback.objects.get(slug=feedback_slug) - instance.delete() - return HttpResponseRedirect(reverse('start')) - - -class FeedbackEdit(UpdateView): - - """docstring for FeedbackCreate""" - - form_class = FeedbackForm - template_name = 'core/feedback_form.html' - success_url = '/start/' - - @method_decorator(group_required('Tutors', 'Reviewers')) - def dispatch(self, *args, **kwargs): - return super(FeedbackEdit, self).dispatch(*args, **kwargs) - - def get_object(self): - instance = Feedback.objects.get(slug=self.kwargs['feedback_slug']) - if instance.of_tutor == self.request.user or in_groups(self.request.user, ('Reviewers', )): - return instance - elif instance.status == Feedback.OPEN: - instance.reassign_to_tutor(self.request.user) - return instance - elif not (instance.of_tutor == self.request.user or in_groups(self.request.user, ('Reviewers', ))): - messages.error( - self.request, "Get your hands of somebody else's feedback!") - raise Http404 - - def form_valid(self, form): - """ - If the form is valid, redirect to the supplied URL. - """ - if form.is_valid(): - form.instance.text = self.request.POST['text'] - if form.instance.status == Feedback.ACCEPTED: - form.instance.finalize_feedback(self.request.user) - else: - form.instance.unfinalize_feedback() - - # ugly needs patch - if 'Next' in self.request.POST['update']: - if in_groups(self.request.user, ('Reviewers',)): - - needs_review = Feedback.objects.filter( - status=Feedback.NEEDS_REVIEW, - of_submission__type=form.instance.of_submission.type - ) - - if needs_review: - return HttpResponseRedirect(reverse('FeedbackEdit', args=(needs_review[0].slug,))) - - else: # in_groups(self.request.user, ('Tutor',)): - return HttpResponseRedirect(reverse('CreateFeedbackForType', args=(form.instance.of_submission.type.slug,))) - - elif 'Save' in self.request.POST['update']: - return HttpResponseRedirect(reverse('FeedbackEdit', args=(form.instance.slug,))) - - return HttpResponseRedirect(self.get_success_url()) - - def get_context_data(self, **kwargs): - context = super(FeedbackEdit, self).get_context_data(**kwargs) - context['grady_says'] = choice(grady_says) - return context - - -@group_required('Reviewers', 'Tutors') -def download_submissions(request, slug): - submission = Submission.objects.get(slug=slug) - - if not (submission.feedback.of_tutor == request.user or in_groups(request.user, ('Reviewers', ))): - messages.error(request, "Get your hands of somebody else's feedback!") - return HttpResponseRedirect(reverse('start')) - - response = HttpResponse(content_type='text/plain') - response['Content-Disposition'] = 'attachment; filename="%s_%s.c"' % ( - submission.type.name, submission.slug) - response.write(submission.text) - - return response diff --git a/core/views/generics.py b/core/views/generics.py deleted file mode 100644 index 6afd8c675c3dc4707226755f5d773e2852fedf20..0000000000000000000000000000000000000000 --- a/core/views/generics.py +++ /dev/null @@ -1,58 +0,0 @@ -from django.utils.decorators import method_decorator -from django.views.generic import DetailView, ListView, View - -from core.custom_annotations import group_required -from core.models import SubmissionType, get_annotated_tutor_list - - -class StudentView(View): - - @method_decorator(group_required('Students',)) - def dispatch(self, *args, **kwargs): - return super().dispatch(*args, **kwargs) - - -class StudentListView(StudentView, ListView): - pass - - -class StudentDetailView(StudentView, DetailView): - pass - - -class TutorView(View): - - @method_decorator(group_required('Tutors',)) - def dispatch(self, *args, **kwargs): - return super().dispatch(*args, **kwargs) - - -class TutorListView(TutorView, ListView): - pass - - -class TutorDetailView(TutorView, DetailView): - pass - - -class ReviewerView(View): - - @method_decorator(group_required('Reviewers',)) - def dispatch(self, *args, **kwargs): - return super().dispatch(*args, **kwargs) - - -class ReviewerListView(ReviewerView, ListView): - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - return { - 'submission_type_list': SubmissionType.get_annotated_feedback_count(), - 'tutor_list': get_annotated_tutor_list(), - **context, - } - - -class ReviewerDetailView(ReviewerView, DetailView): - pass diff --git a/core/views/index.py b/core/views/index.py deleted file mode 100644 index 24fa020f9d7cdd698d48b20319976b9ecab68a96..0000000000000000000000000000000000000000 --- a/core/views/index.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.views.generic import TemplateView - - -class IndexView(TemplateView): - template_name = 'core/index.html' diff --git a/core/views/login.py b/core/views/login.py deleted file mode 100644 index 33243ef7a1b167e27b89f76e0514ed5d7b20f31b..0000000000000000000000000000000000000000 --- a/core/views/login.py +++ /dev/null @@ -1,64 +0,0 @@ -from django.contrib import messages -from django.contrib.auth import authenticate, login -from django.contrib.auth.views import LoginView, LogoutView -from django.http import HttpResponseRedirect -from django.urls import reverse, reverse_lazy - -from core.custom_annotations import in_groups - - -def is_student(user): - return in_groups(user, ('Students',)) - -def is_deactivated_student(user) -> bool: - """Checks if the user is linked to a student and if the field user - has_logged_in is True or not. Obviously a superuser should not be a student. - - Args: - user (User object): The original user of some request. - - Returns: - bool: True if user is a student and has already logged in - """ - if user.is_superuser: - return False - - if in_groups(user, ('Students',)): - return user.student.has_logged_in - -class Login(LoginView): - - success_url = reverse_lazy('start') - template_name = 'core/index.html' - - def get(self, request): - return HttpResponseRedirect(reverse('index')) - - def form_valid(self, form): - username = form.cleaned_data['username'] - password = form.cleaned_data['password'] - - user = authenticate(username=username, password=password) - - if user is not None and user.is_active and not is_deactivated_student(user): - login(self.request, user) - - # disable the user if s/he is a student - if is_student(user) and not user.is_superuser: - user.student.disable() - - print(self.get_success_url()) - return HttpResponseRedirect(self.get_success_url()) - - # Handle all the errors separately - if is_deactivated_student(user) or not user.is_active: - messages.warning(self.request, "Your Grady account has been deactivated.") - elif not user: - # Bad login details were provided. So we can't log the user in. - print("Invalid login details: {0}, {1}".format(username, password)) - messages.error(self.request, "Invalid login details supplied.") - - return super().form_invalid(form) - -class Logout(LogoutView): - next_page = reverse_lazy('index') diff --git a/core/views/submission.py b/core/views/submission.py deleted file mode 100644 index 8d7eff78bfe5f9a5572f091d1c2284826a87916d..0000000000000000000000000000000000000000 --- a/core/views/submission.py +++ /dev/null @@ -1,45 +0,0 @@ -from django.views.generic import DetailView - -from core.custom_annotations import in_groups -from core.models import Feedback, Student, Submission -from core.views.generics import (ReviewerDetailView, ReviewerListView, - StudentView) - - -class StudentSubmissionView(StudentView, DetailView): - - template_name = 'core/s/single_submission.html' - model = Submission - - def get_object(self): - obj = Submission.objects.get(slug=self.kwargs['slug']) - if in_groups(self.request.user, ('Students', )) and hasattr(obj, 'feedback') and obj.feedback.status == Feedback.ACCEPTED: - obj.seen_by_student = True - obj.save() - return obj - - -class ReviewerSubmissionView(ReviewerDetailView): - - model = Submission - template_name = 'core/r/single_submission.html' - - def get_object(self): - return Submission.objects.get(slug=self.kwargs['slug']) - - -class ReviewerSubmissionListView(ReviewerListView): - - model = Submission - template_name = 'core/r/student_submission_list.html' - context_object_name = 'submission_list' - - -class ReviewerStudentListView(ReviewerListView): - - model = Student - template_name = 'core/r/student_list.html' - context_object_name = 'student_list' - - def get_queryset(self): - return self.model.get_overall_score_annotated_submission_list() diff --git a/core/views/user_startpages.py b/core/views/user_startpages.py deleted file mode 100644 index 9d1ae9803b5204044d8e9825b28a45b4dd3d78b1..0000000000000000000000000000000000000000 --- a/core/views/user_startpages.py +++ /dev/null @@ -1,67 +0,0 @@ -from django.contrib.auth.decorators import login_required -from django.contrib.auth.models import User -from django.http import HttpResponseRedirect -from django.urls import reverse - -from core.custom_annotations import in_groups -from core.models import Feedback, Student, SubmissionType -from core.views.generics import (ReviewerListView, StudentDetailView, - TutorDetailView) - - -@login_required(login_url='/') -def user_home(request): - if in_groups(request.user, ('Students', )): - return StudentStartPage.as_view()(request) - elif in_groups(request.user, ('Tutors', )): - return TutorStartPage.as_view()(request) - elif in_groups(request.user, ('Reviewers', )): - return ReviewerFeedbackListView.as_view()(request) - else: - return HttpResponseRedirect(reverse('index')) - - -class TutorStartPage(TutorDetailView): - - model = User - template_name = 'core/t/tutor_startpage.html' - context_object_name = 'tutor' - - def get_object(self): - return self.request.user - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - return { - 'submission_type_list': SubmissionType.get_annotated_feedback_count(), - 'feedback_open_list': Feedback.get_open_feedback(self.get_object()), - **context - } - - -class StudentStartPage(StudentDetailView): - - model = Student - template_name = 'core/s/student_startpage.html' - - def get_object(self): - return self.request.user.student - - -class ReviewerFeedbackListView(ReviewerListView): - """ This is the de facto startpage of the reviewer accounts""" - - model = Feedback - template_name = 'core/r/reviewer_startpage.html' - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - return { - 'feedback_list_manual': self.model.objects.filter(origin=Feedback.MANUAL), - 'feedback_list_empty': self.model.objects.filter(origin=Feedback.WAS_EMPTY), - 'feedback_list_did_not_compile': self.model.objects.filter(origin=Feedback.DID_NOT_COMPILE), - 'feedback_list_could_not_link': self.model.objects.filter(origin=Feedback.COULD_NOT_LINK), - **context - } diff --git a/docker-compose.yml b/docker-compose.yml index f4bf724fa53027d40d834de7c5d669a84aa362f5..d85cfb636e4bbdaba7325592190f96790d8520cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,16 +9,11 @@ services: - /bin/sh - -c - | - python manage.py collectstatic --ignore node_modules --noinput --clear - python manage.py compress --force python manage.py migrate --noinput - python manage.py loaddata core/fixtures/testdata-groups.json - python manage.py loaddata core/fixtures/testdata-user.json - python manage.py loaddata core/fixtures/testdata-core.json - gunicorn --bind 0.0.0.0:8000 grady.wsgi:application + gunicorn --bind 0.0.0.0:8000 grady.wsgi:application & + cd static/ && python -m http.server 8080 ports: - "8000:8000" - volumes: - - /var/www/static:/code/static + - "8080:8080" depends_on: - postgres diff --git a/frontend/.babelrc b/frontend/.babelrc new file mode 100644 index 0000000000000000000000000000000000000000..c06df4d53a2308f7a59b40455f4ed47e91d776f6 --- /dev/null +++ b/frontend/.babelrc @@ -0,0 +1,18 @@ +{ + "presets": [ + ["env", { + "modules": false, + "targets": { + "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] + } + }], + "stage-2" + ], + "plugins": ["transform-runtime"], + "env": { + "test": { + "presets": ["env", "stage-2"], + "plugins": ["istanbul"] + } + } +} diff --git a/frontend/.editorconfig b/frontend/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..9d08a1a828a3bd2d60de3952744df29f9add27fa --- /dev/null +++ b/frontend/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 0000000000000000000000000000000000000000..34af3774f3127d054d30ac5452f8afc08cdd0291 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,2 @@ +build/*.js +config/*.js diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..e0dd62d911761e70c387d89fbc29ecb4b4d8746e --- /dev/null +++ b/frontend/.eslintrc.js @@ -0,0 +1,27 @@ +// https://eslint.org/docs/user-guide/configuring + +module.exports = { + root: true, + parser: 'babel-eslint', + parserOptions: { + sourceType: 'module' + }, + env: { + browser: true, + }, + // https://github.com/standard/standard/blob/master/docs/RULES-en.md + extends: 'standard', + // required to lint *.vue files + plugins: [ + 'html' + ], + // add your custom rules here + 'rules': { + // allow paren-less arrow functions + 'arrow-parens': 0, + // allow async-await + 'generator-star-spacing': 0, + // allow debugger during development + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 + } +} diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c87fa678827a2f5d3efd5057b94ce30c41acbf5a --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,15 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +test/unit/coverage + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/frontend/.postcssrc.js b/frontend/.postcssrc.js new file mode 100644 index 0000000000000000000000000000000000000000..09948d63e91b03d9880bb5a1cbbf822a3a2f2065 --- /dev/null +++ b/frontend/.postcssrc.js @@ -0,0 +1,8 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + "plugins": { + // to edit target browsers: use "browserslist" field in package.json + "autoprefixer": {} + } +} diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000000000000000000000000000000000000..450a662ef31342b1705aeffdd2e0f591579850df --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,27 @@ +# frontend + +> Vue.js frontend for Grady + +## Build Setup + +``` bash +# install dependencies +npm install + +# serve with hot reload at localhost:8080 +npm run dev + +# build for production with minification +npm run build + +# build for production and view the bundle analyzer report +npm run build --report + +# run unit tests +npm run unit + +# run all tests +npm test +``` + +For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). diff --git a/frontend/build/build.js b/frontend/build/build.js new file mode 100644 index 0000000000000000000000000000000000000000..30f036a1806fed8edf6880a6cdbc0971d8bc0d2e --- /dev/null +++ b/frontend/build/build.js @@ -0,0 +1,41 @@ +'use strict' +require('./check-versions')() + +process.env.NODE_ENV = 'production' + +const ora = require('ora') +const rm = require('rimraf') +const path = require('path') +const chalk = require('chalk') +const webpack = require('webpack') +const config = require('../config') +const webpackConfig = require('./webpack.prod.conf') + +const spinner = ora('building for production...') +spinner.start() + +rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { + if (err) throw err + webpack(webpackConfig, function (err, stats) { + spinner.stop() + if (err) throw err + process.stdout.write(stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false + }) + '\n\n') + + if (stats.hasErrors()) { + console.log(chalk.red(' Build failed with errors.\n')) + process.exit(1) + } + + console.log(chalk.cyan(' Build complete.\n')) + console.log(chalk.yellow( + ' Tip: built files are meant to be served over an HTTP server.\n' + + ' Opening index.html over file:// won\'t work.\n' + )) + }) +}) diff --git a/frontend/build/check-versions.js b/frontend/build/check-versions.js new file mode 100644 index 0000000000000000000000000000000000000000..ca407bb16ff339aa36c520e7f0133204cca2b2ab --- /dev/null +++ b/frontend/build/check-versions.js @@ -0,0 +1,49 @@ +'use strict' +const chalk = require('chalk') +const semver = require('semver') +const packageConfig = require('../package.json') +const shell = require('shelljs') +function exec (cmd) { + return require('child_process').execSync(cmd).toString().trim() +} + +const versionRequirements = [ + { + name: 'node', + currentVersion: semver.clean(process.version), + versionRequirement: packageConfig.engines.node + } +] + +if (shell.which('npm')) { + versionRequirements.push({ + name: 'npm', + currentVersion: exec('npm --version'), + versionRequirement: packageConfig.engines.npm + }) +} + +module.exports = function () { + const warnings = [] + for (let i = 0; i < versionRequirements.length; i++) { + const mod = versionRequirements[i] + if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { + warnings.push(mod.name + ': ' + + chalk.red(mod.currentVersion) + ' should be ' + + chalk.green(mod.versionRequirement) + ) + } + } + + if (warnings.length) { + console.log('') + console.log(chalk.yellow('To use this template, you must update following to modules:')) + console.log() + for (let i = 0; i < warnings.length; i++) { + const warning = warnings[i] + console.log(' ' + warning) + } + console.log() + process.exit(1) + } +} diff --git a/frontend/build/dev-client.js b/frontend/build/dev-client.js new file mode 100644 index 0000000000000000000000000000000000000000..2f75dd531f320c9c08a0bdb61788a2f1a013825b --- /dev/null +++ b/frontend/build/dev-client.js @@ -0,0 +1,10 @@ +/* eslint-disable */ +'use strict' +require('eventsource-polyfill') +var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') + +hotClient.subscribe(function (event) { + if (event.action === 'reload') { + window.location.reload() + } +}) diff --git a/frontend/build/dev-server.js b/frontend/build/dev-server.js new file mode 100644 index 0000000000000000000000000000000000000000..bcb5c0728d6b5bf448591ac65dec2f76c734ce96 --- /dev/null +++ b/frontend/build/dev-server.js @@ -0,0 +1,107 @@ +'use strict' +require('./check-versions')() + +const config = require('../config') +if (!process.env.NODE_ENV) { + process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) +} + +const opn = require('opn') +const path = require('path') +const express = require('express') +const webpack = require('webpack') +const proxyMiddleware = require('http-proxy-middleware') +const webpackConfig = (process.env.NODE_ENV === 'testing' || process.env.NODE_ENV === 'production') + ? require('./webpack.prod.conf') + : require('./webpack.dev.conf') + +// default port where dev server listens for incoming traffic +const port = process.env.PORT || config.dev.port +// automatically open browser, if not set will be false +const autoOpenBrowser = !!config.dev.autoOpenBrowser +// Define HTTP proxies to your custom API backend +// https://github.com/chimurai/http-proxy-middleware +const proxyTable = config.dev.proxyTable + +const app = express() +const compiler = webpack(webpackConfig) + +const devMiddleware = require('webpack-dev-middleware')(compiler, { + publicPath: webpackConfig.output.publicPath, + quiet: true +}) + +const hotMiddleware = require('webpack-hot-middleware')(compiler, { + log: false, + heartbeat: 2000 +}) +// force page reload when html-webpack-plugin template changes +// currently disabled until this is resolved: +// https://github.com/jantimon/html-webpack-plugin/issues/680 +// compiler.plugin('compilation', function (compilation) { +// compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { +// hotMiddleware.publish({ action: 'reload' }) +// cb() +// }) +// }) + +// enable hot-reload and state-preserving +// compilation error display +app.use(hotMiddleware) + +// proxy api requests +Object.keys(proxyTable).forEach(function (context) { + let options = proxyTable[context] + if (typeof options === 'string') { + options = { target: options } + } + app.use(proxyMiddleware(options.filter || context, options)) +}) + +// handle fallback for HTML5 history API +app.use(require('connect-history-api-fallback')()) + +// serve webpack bundle output +app.use(devMiddleware) + +// serve pure static assets +const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) +app.use(staticPath, express.static('./static')) + +const uri = 'http://localhost:' + port + +var _resolve +var _reject +var readyPromise = new Promise((resolve, reject) => { + _resolve = resolve + _reject = reject +}) + +var server +var portfinder = require('portfinder') +portfinder.basePort = port + +console.log('> Starting dev server...') +devMiddleware.waitUntilValid(() => { + portfinder.getPort((err, port) => { + if (err) { + _reject(err) + } + process.env.PORT = port + var uri = 'http://localhost:' + port + console.log('> Listening at ' + uri + '\n') + // when env is testing, don't need open it + if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { + opn(uri) + } + server = app.listen(port) + _resolve() + }) +}) + +module.exports = { + ready: readyPromise, + close: () => { + server.close() + } +} diff --git a/frontend/build/utils.js b/frontend/build/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..4ac71cb2c9b7d3b3edae36de3055e5c279bc40ed --- /dev/null +++ b/frontend/build/utils.js @@ -0,0 +1,72 @@ +'use strict' +const path = require('path') +const config = require('../config') +const ExtractTextPlugin = require('extract-text-webpack-plugin') + +exports.assetsPath = function (_path) { + const assetsSubDirectory = process.env.NODE_ENV === 'production' + ? config.build.assetsSubDirectory + : config.dev.assetsSubDirectory + return path.posix.join(assetsSubDirectory, _path) +} + +exports.cssLoaders = function (options) { + options = options || {} + + const cssLoader = { + loader: 'css-loader', + options: { + minimize: process.env.NODE_ENV === 'production', + sourceMap: options.sourceMap + } + } + + // generate loader string to be used with extract text plugin + function generateLoaders (loader, loaderOptions) { + const loaders = [cssLoader] + if (loader) { + loaders.push({ + loader: loader + '-loader', + options: Object.assign({}, loaderOptions, { + sourceMap: options.sourceMap + }) + }) + } + + // Extract CSS when that option is specified + // (which is the case during production build) + if (options.extract) { + return ExtractTextPlugin.extract({ + use: loaders, + fallback: 'vue-style-loader' + }) + } else { + return ['vue-style-loader'].concat(loaders) + } + } + + // https://vue-loader.vuejs.org/en/configurations/extract-css.html + return { + css: generateLoaders(), + postcss: generateLoaders(), + less: generateLoaders('less'), + sass: generateLoaders('sass', { indentedSyntax: true }), + scss: generateLoaders('sass'), + stylus: generateLoaders('stylus'), + styl: generateLoaders('stylus') + } +} + +// Generate loaders for standalone style files (outside of .vue) +exports.styleLoaders = function (options) { + const output = [] + const loaders = exports.cssLoaders(options) + for (const extension in loaders) { + const loader = loaders[extension] + output.push({ + test: new RegExp('\\.' + extension + '$'), + use: loader + }) + } + return output +} diff --git a/frontend/build/vue-loader.conf.js b/frontend/build/vue-loader.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..eece58fe1b7eb9486746ad9449dbe41f2e85fb42 --- /dev/null +++ b/frontend/build/vue-loader.conf.js @@ -0,0 +1,19 @@ +'use strict' +const utils = require('./utils') +const config = require('../config') +const isProduction = process.env.NODE_ENV === 'production' + +module.exports = { + loaders: utils.cssLoaders({ + sourceMap: isProduction + ? config.build.productionSourceMap + : config.dev.cssSourceMap, + extract: isProduction + }), + transformToRequire: { + video: 'src', + source: 'src', + img: 'src', + image: 'xlink:href' + } +} diff --git a/frontend/build/webpack.base.conf.js b/frontend/build/webpack.base.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..6920efe7e6e85446cd4f00e46f27958cc74d4580 --- /dev/null +++ b/frontend/build/webpack.base.conf.js @@ -0,0 +1,76 @@ +'use strict' +const path = require('path') +const utils = require('./utils') +const config = require('../config') +const vueLoaderConfig = require('./vue-loader.conf') + +function resolve (dir) { + return path.join(__dirname, '..', dir) +} + +module.exports = { + entry: { + app: './src/main.js' + }, + output: { + path: config.build.assetsRoot, + filename: '[name].js', + publicPath: process.env.NODE_ENV === 'production' + ? config.build.assetsPublicPath + : config.dev.assetsPublicPath + }, + resolve: { + extensions: ['.js', '.vue', '.json'], + alias: { + 'vue$': 'vue/dist/vue.esm.js', + '@': resolve('src'), + } + }, + module: { + rules: [ + { + test: /\.(js|vue)$/, + loader: 'eslint-loader', + enforce: 'pre', + include: [resolve('src'), resolve('test')], + options: { + formatter: require('eslint-friendly-formatter') + } + }, + { + test: /\.vue$/, + loader: 'vue-loader', + options: vueLoaderConfig + }, + { + test: /\.js$/, + loader: 'babel-loader', + include: [resolve('src'), resolve('test')] + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]') + } + }, + { + test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('media/[name].[hash:7].[ext]') + } + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('fonts/[name].[hash:7].[ext]') + } + } + ] + } +} diff --git a/frontend/build/webpack.dev.conf.js b/frontend/build/webpack.dev.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..6f25d634588c7f722f71d0f50f11632220a6d5d6 --- /dev/null +++ b/frontend/build/webpack.dev.conf.js @@ -0,0 +1,36 @@ +'use strict' +const utils = require('./utils') +const webpack = require('webpack') +const config = require('../config') +const merge = require('webpack-merge') +const baseWebpackConfig = require('./webpack.base.conf') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') + +// add hot-reload related code to entry chunks +Object.keys(baseWebpackConfig.entry).forEach(function (name) { + baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) +}) + +module.exports = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) + }, + // cheap-module-eval-source-map is faster for development + devtool: '#cheap-module-eval-source-map', + plugins: [ + new webpack.DefinePlugin({ + 'process.env': config.dev.env + }), + // https://github.com/glenjamin/webpack-hot-middleware#installation--usage + new webpack.HotModuleReplacementPlugin(), + new webpack.NoEmitOnErrorsPlugin(), + // https://github.com/ampedandwired/html-webpack-plugin + new HtmlWebpackPlugin({ + filename: 'index.html', + template: 'index.html', + inject: true + }), + new FriendlyErrorsPlugin() + ] +}) diff --git a/frontend/build/webpack.prod.conf.js b/frontend/build/webpack.prod.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..9874990e16b70eb6cc91aee5876704d4d2b64b69 --- /dev/null +++ b/frontend/build/webpack.prod.conf.js @@ -0,0 +1,128 @@ +'use strict' +const path = require('path') +const utils = require('./utils') +const webpack = require('webpack') +const config = require('../config') +const merge = require('webpack-merge') +const baseWebpackConfig = require('./webpack.base.conf') +const CopyWebpackPlugin = require('copy-webpack-plugin') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const ExtractTextPlugin = require('extract-text-webpack-plugin') +const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') + +const env = process.env.NODE_ENV === 'testing' + ? require('../config/test.env') + : config.build.env + +const webpackConfig = merge(baseWebpackConfig, { + module: { + rules: utils.styleLoaders({ + sourceMap: config.build.productionSourceMap, + extract: true + }) + }, + devtool: config.build.productionSourceMap ? '#source-map' : false, + output: { + path: config.build.assetsRoot, + filename: utils.assetsPath('js/[name].[chunkhash].js'), + chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') + }, + plugins: [ + // http://vuejs.github.io/vue-loader/en/workflow/production.html + new webpack.DefinePlugin({ + 'process.env': env + }), + // UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + }, + sourceMap: true + }), + // extract css into its own file + new ExtractTextPlugin({ + filename: utils.assetsPath('css/[name].[contenthash].css') + }), + // Compress extracted CSS. We are using this plugin so that possible + // duplicated CSS from different components can be deduped. + new OptimizeCSSPlugin({ + cssProcessorOptions: { + safe: true + } + }), + // generate dist index.html with correct asset hash for caching. + // you can customize output by editing /index.html + // see https://github.com/ampedandwired/html-webpack-plugin + new HtmlWebpackPlugin({ + filename: process.env.NODE_ENV === 'testing' + ? 'index.html' + : config.build.index, + template: 'index.html', + inject: true, + minify: { + removeComments: true, + collapseWhitespace: true, + removeAttributeQuotes: true + // more options: + // https://github.com/kangax/html-minifier#options-quick-reference + }, + // necessary to consistently work with multiple chunks via CommonsChunkPlugin + chunksSortMode: 'dependency' + }), + // keep module.id stable when vender modules does not change + new webpack.HashedModuleIdsPlugin(), + // split vendor js into its own file + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + minChunks: function (module) { + // any required modules inside node_modules are extracted to vendor + return ( + module.resource && + /\.js$/.test(module.resource) && + module.resource.indexOf( + path.join(__dirname, '../node_modules') + ) === 0 + ) + } + }), + // extract webpack runtime and module manifest to its own file in order to + // prevent vendor hash from being updated whenever app bundle is updated + new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest', + chunks: ['vendor'] + }), + // copy custom static assets + new CopyWebpackPlugin([ + { + from: path.resolve(__dirname, '../static'), + to: config.build.assetsSubDirectory, + ignore: ['.*'] + } + ]) + ] +}) + +if (config.build.productionGzip) { + const CompressionWebpackPlugin = require('compression-webpack-plugin') + + webpackConfig.plugins.push( + new CompressionWebpackPlugin({ + asset: '[path].gz[query]', + algorithm: 'gzip', + test: new RegExp( + '\\.(' + + config.build.productionGzipExtensions.join('|') + + ')$' + ), + threshold: 10240, + minRatio: 0.8 + }) + ) +} + +if (config.build.bundleAnalyzerReport) { + const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin + webpackConfig.plugins.push(new BundleAnalyzerPlugin()) +} + +module.exports = webpackConfig diff --git a/frontend/build/webpack.test.conf.js b/frontend/build/webpack.test.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..0d658d9ebe5288866a1161bd7202dceccee665f0 --- /dev/null +++ b/frontend/build/webpack.test.conf.js @@ -0,0 +1,32 @@ +'use strict' +// This is the webpack config used for unit tests. + +const utils = require('./utils') +const webpack = require('webpack') +const merge = require('webpack-merge') +const baseWebpackConfig = require('./webpack.base.conf') + +const webpackConfig = merge(baseWebpackConfig, { + // use inline sourcemap for karma-sourcemap-loader + module: { + rules: utils.styleLoaders() + }, + devtool: '#inline-source-map', + resolveLoader: { + alias: { + // necessary to to make lang="scss" work in test when using vue-loader's ?inject option + // see discussion at https://github.com/vuejs/vue-loader/issues/724 + 'scss-loader': 'sass-loader' + } + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': require('../config/test.env') + }) + ] +}) + +// no need for app entry during tests +delete webpackConfig.entry + +module.exports = webpackConfig diff --git a/frontend/config/dev.env.js b/frontend/config/dev.env.js new file mode 100644 index 0000000000000000000000000000000000000000..1e22973ae71e949faa15f7a8ab392786918fb22d --- /dev/null +++ b/frontend/config/dev.env.js @@ -0,0 +1,7 @@ +'use strict' +const merge = require('webpack-merge') +const prodEnv = require('./prod.env') + +module.exports = merge(prodEnv, { + NODE_ENV: '"development"' +}) diff --git a/frontend/config/index.js b/frontend/config/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2c458f66802f5f8d206f4f136a0b5d52b59b4c21 --- /dev/null +++ b/frontend/config/index.js @@ -0,0 +1,42 @@ + +'use strict' +// Template version: 1.1.3 +// see http://vuejs-templates.github.io/webpack for documentation. + +const path = require('path') + +module.exports = { + build: { + env: require('./prod.env'), + index: path.resolve(__dirname, '../dist/index.html'), + assetsRoot: path.resolve(__dirname, '../dist'), + assetsSubDirectory: 'static', + assetsPublicPath: '/', + productionSourceMap: true, + // Gzip off by default as many popular static hosts such as + // Surge or Netlify already gzip all static assets for you. + // Before setting to `true`, make sure to: + // npm install --save-dev compression-webpack-plugin + productionGzip: false, + productionGzipExtensions: ['js', 'css'], + // Run the build command with an extra argument to + // View the bundle analyzer report after build finishes: + // `npm run build --report` + // Set to `true` or `false` to always turn it on or off + bundleAnalyzerReport: process.env.npm_config_report + }, + dev: { + env: require('./dev.env'), + port: process.env.PORT || 8080, + autoOpenBrowser: true, + assetsSubDirectory: 'static', + assetsPublicPath: '/', + proxyTable: {}, + // CSS Sourcemaps off by default because relative paths are "buggy" + // with this option, according to the CSS-Loader README + // (https://github.com/webpack/css-loader#sourcemaps) + // In our experience, they generally work as expected, + // just be aware of this issue when enabling this option. + cssSourceMap: false + } +} diff --git a/frontend/config/prod.env.js b/frontend/config/prod.env.js new file mode 100644 index 0000000000000000000000000000000000000000..a6f997616eff680e4b2d437e7f31de2cadbfa1de --- /dev/null +++ b/frontend/config/prod.env.js @@ -0,0 +1,4 @@ +'use strict' +module.exports = { + NODE_ENV: '"production"' +} diff --git a/frontend/config/test.env.js b/frontend/config/test.env.js new file mode 100644 index 0000000000000000000000000000000000000000..c2824a307a33e7243d96e29b12ad518f8cf16aa3 --- /dev/null +++ b/frontend/config/test.env.js @@ -0,0 +1,7 @@ +'use strict' +const merge = require('webpack-merge') +const devEnv = require('./dev.env') + +module.exports = merge(devEnv, { + NODE_ENV: '"testing"' +}) diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..fb63c5378340aee23aac55a9168ec7067cb63066 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>frontend</title> + </head> + <body> + <div id="app"></div> + <!-- built files will be auto injected --> + </body> +</html> diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..e657774de9bfafaaaf987fd6ad46799fa65c1307 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,95 @@ +{ + "name": "frontend", + "version": "1.0.0", + "description": "Vue.js frontend for Grady", + "author": "robinwilliam.hundt <robinwilliam.hundt@stud.uni-goettingen.de>", + "private": true, + "scripts": { + "dev": "node build/dev-server.js", + "start": "npm run dev", + "build": "node build/build.js", + "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", + "test": "karma start test/unit/karma.conf.js", + "lint": "eslint --ext .js,.vue src test/unit/specs" + }, + "dependencies": { + "axios": "^0.17.0", + "vue": "^2.5.2", + "vue-router": "^3.0.1", + "vuetify": "^0.16.9", + "vuex": "^3.0.1" + }, + "devDependencies": { + "autoprefixer": "^7.1.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-loader": "^7.1.1", + "babel-plugin-istanbul": "^4.1.1", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-preset-env": "^1.3.2", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "chai": "^4.1.2", + "chalk": "^2.0.1", + "connect-history-api-fallback": "^1.3.0", + "copy-webpack-plugin": "^4.0.1", + "cross-env": "^5.0.1", + "css-loader": "^0.28.7", + "es6-promise": "^4.1.1", + "eslint": "^3.19.0", + "eslint-config-standard": "^10.2.1", + "eslint-friendly-formatter": "^3.0.0", + "eslint-loader": "^1.7.1", + "eslint-plugin-html": "^3.0.0", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.2.0", + "eslint-plugin-promise": "^3.4.0", + "eslint-plugin-standard": "^3.0.1", + "eventsource-polyfill": "^0.9.6", + "express": "^4.14.1", + "extract-text-webpack-plugin": "^3.0.0", + "file-loader": "^1.1.4", + "friendly-errors-webpack-plugin": "^1.6.1", + "html-webpack-plugin": "^2.30.1", + "http-proxy-middleware": "^0.17.3", + "inject-loader": "^3.0.0", + "karma": "^1.4.1", + "karma-coverage": "^1.1.1", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-phantomjs-shim": "^1.4.0", + "karma-sinon-chai": "^1.3.1", + "karma-sourcemap-loader": "^0.3.7", + "karma-spec-reporter": "0.0.31", + "karma-webpack": "^2.0.2", + "mocha": "^3.2.0", + "opn": "^5.1.0", + "optimize-css-assets-webpack-plugin": "^3.2.0", + "ora": "^1.2.0", + "phantomjs-prebuilt": "^2.1.14", + "portfinder": "^1.0.13", + "rimraf": "^2.6.0", + "semver": "^5.3.0", + "shelljs": "^0.7.6", + "sinon": "^4.0.0", + "sinon-chai": "^2.8.0", + "url-loader": "^0.5.8", + "vue-loader": "^13.3.0", + "vue-style-loader": "^3.0.1", + "vue-template-compiler": "^2.5.2", + "webpack": "^3.6.0", + "webpack-bundle-analyzer": "^2.9.0", + "webpack-dev-middleware": "^1.12.0", + "webpack-hot-middleware": "^2.18.2", + "webpack-merge": "^4.1.0" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000000000000000000000000000000000000..64fcd76cf6a10610db451677e80912d837ffaeae --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,21 @@ +<template> + <div id="app"> + <v-app> + <router-view/> + </v-app> + </div> +</template> + +<script> + export default { + name: 'app', + components: { + } +} +</script> + +<style> +#app { + +} +</style> diff --git a/core/static/res/brand.png b/frontend/src/assets/brand.png similarity index 100% rename from core/static/res/brand.png rename to frontend/src/assets/brand.png diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2503fc2a44b5053b0837ebea6e87a2d339a43 Binary files /dev/null and b/frontend/src/assets/logo.png differ diff --git a/frontend/src/components/Login.vue b/frontend/src/components/Login.vue new file mode 100644 index 0000000000000000000000000000000000000000..325fa0c94f1e29107e295f3098003aecb0290010 --- /dev/null +++ b/frontend/src/components/Login.vue @@ -0,0 +1,55 @@ +<template> + <v-container fill-height> + <v-layout align-center justify-center> + <v-flex text-xs-center md4 lg2> + <img src="../assets/brand.png"/> + <h3 class="pt-3">Log in</h3> + <p>But I corrected them, sir.</p> + + <v-form> + <v-text-field + label="Username" + v-model="credentials.username" + required></v-text-field> + <v-text-field + label="Password" + v-model="credentials.password" + type="password" + required></v-text-field> + </v-form> + <v-btn color="primary" @click="submit()">Access</v-btn> + </v-flex> + </v-layout> + </v-container> +</template> + + +<script> + export default { + name: 'grady-login', + data () { + return { + credentials: { + username: '', + password: '' + }, + error: '' + } + }, + methods: { + submit () { + const credentials = { + username: this.credentials.username, + password: this.credentials.password + } + this.$store.dispatch('getToken', credentials).then(response => { + this.$router.push('/student/') + }) + } + } + } +</script> + + +<style scoped> +</style> diff --git a/frontend/src/components/student/ExamInformation.vue b/frontend/src/components/student/ExamInformation.vue new file mode 100644 index 0000000000000000000000000000000000000000..817cd58c1e42da874890066be1d87409c4d5e4cd --- /dev/null +++ b/frontend/src/components/student/ExamInformation.vue @@ -0,0 +1,29 @@ +<template> + <table class="table table-info rounded"> + <tbody> + <tr> + <th>Modul</th> + <td>{{ exam.module_reference }}</td> + </tr> + <tr v-if="!exam.pass_only"> + <th>Pass score</th> + <td>{{ exam.pass_score }}</td> + </tr> + <tr v-else> + <th>Pass only!</th> + </tr> + <tr> + <th>Total score</th> + <td>{{ exam.total_score }}</td> + </tr> + </tbody> + </table> +</template> + + +<script> + export default { + name: 'exam-information', + props: ['exam'] + } +</script> diff --git a/frontend/src/components/student/StudentNav.vue b/frontend/src/components/student/StudentNav.vue new file mode 100644 index 0000000000000000000000000000000000000000..6613a097b7116f3935298a0d4db14d817fe5cabd --- /dev/null +++ b/frontend/src/components/student/StudentNav.vue @@ -0,0 +1,38 @@ +<template> + <b-navbar toggleable="md" type="light" variant="light"> + <b-navbar-toggle target="nav_collapse"></b-navbar-toggle> + + <b-navbar-brand> + <img src="../../assets/brand.png" width="30" class="d-inline-block align-top"> + Grady + </b-navbar-brand> + + <b-collapse is-nav id="nav_collapse"> + + <b-navbar-nav id="nav-left"> + <b-nav-item class="active" href="#">Results</b-nav-item> + <b-nav-item href="#">Statistics</b-nav-item> + </b-navbar-nav> + + <!-- Right aligned nav items --> + <b-navbar-nav class="ml-auto"> + <b-nav-item>{{ this.$store.state.username }}</b-nav-item> + <router-link to="/"> + <b-button class="btn-dark" @click="logout()" >Signout</b-button> + </router-link> + </b-navbar-nav> + </b-collapse> + </b-navbar> +</template> + + +<script> + export default { + name: 'grady-nav', + methods: { + logout () { + this.$store.dispatch('logout') + } + } + } +</script> diff --git a/frontend/src/components/student/StudentPage.vue b/frontend/src/components/student/StudentPage.vue new file mode 100644 index 0000000000000000000000000000000000000000..b1e9249692fde918bbbfb6f48106301ed3fb62ef --- /dev/null +++ b/frontend/src/components/student/StudentPage.vue @@ -0,0 +1,57 @@ +<template> + <div> + <grady-nav></grady-nav> + <div class="container-fluid"> + <div class="row justify-content-center my-3"> + <div class="col-md-3"> + <h2 class="my-5">Exam Overview</h2> + <exam-information v-if="doneLoading" :exam="exam"></exam-information> + </div> + <div class="col-md-6 offset-md-1" v-if="doneLoading"> + <h2 class="my-5">Submissions of {{ this.studentData.name }}</h2> + <submission-list :submissions="submissions"></submission-list> + </div> + </div> + </div> + </div> +</template> + + +<script> + import ax from '@/store/api' + import GradyNav from './StudentNav.vue' + import SubmissionList from './SubmissionList.vue' + import ExamInformation from './ExamInformation.vue' + + export default { + components: { + ExamInformation, + SubmissionList, + GradyNav}, + name: 'student-page', + data () { + return { + studentData: {}, + doneLoading: false + } + }, + created: function () { + this.doneLoading = false + ax.get('api/student/').then(response => { + this.studentData = response.data + this.doneLoading = true + }) + }, + computed: { + submissions () { + return this.studentData.submissions + }, + exam () { + return this.studentData.exam + } + } + } +</script> + +<style scoped> +</style> diff --git a/frontend/src/components/student/SubmissionList.vue b/frontend/src/components/student/SubmissionList.vue new file mode 100644 index 0000000000000000000000000000000000000000..c39e745fc152cca06a50428cc0f9fe595b858230 --- /dev/null +++ b/frontend/src/components/student/SubmissionList.vue @@ -0,0 +1,36 @@ +<template> + <div class="row my-2 justify-content-center"> + <b-table hover :items="submissions" :fields="fields"></b-table> + <div class="alert alert-info"> + You reached <b>{{ sumScore }}</b> of <b>{{ sumFullScore }}</b> possible points( {{ pointRatio }}% ). + </div> + </div> +</template> + + +<script> + export default { + name: 'submission-list', + data () { + return { + fields: [ + { key: 'type', sortable: true }, + { key: 'score', label: 'Score', sortable: true }, + { key: 'full_score', sortable: true } + ] + } + }, + props: ['submissions'], + computed: { + sumScore () { + return this.submissions.map(a => a.score).reduce((a, b) => a + b) + }, + sumFullScore () { + return this.submissions.map(a => a.full_score).reduce((a, b) => a + b) + }, + pointRatio () { + return ((this.sumScore / this.sumFullScore) * 100).toFixed(2) + } + } + } +</script> diff --git a/frontend/src/main.js b/frontend/src/main.js new file mode 100644 index 0000000000000000000000000000000000000000..997422b82770d3b595a39127ea98f36215f9c98c --- /dev/null +++ b/frontend/src/main.js @@ -0,0 +1,22 @@ +// The Vue build version to load with the `import` command +// (runtime-only or standalone) has been set in webpack.base.conf with an alias. +import Vue from 'vue' +import App from './App' +import router from './router' +import store from './store/store' +import Vuetify from 'vuetify' + +import 'vuetify/dist/vuetify.min.css' + +Vue.use(Vuetify) + +Vue.config.productionTip = false + +/* eslint-disable no-new */ +new Vue({ + el: '#app', + store, + router, + template: '<App/>', + components: { App } +}) diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js new file mode 100644 index 0000000000000000000000000000000000000000..c29cbc7da105a411223133581fbde9ddec64aace --- /dev/null +++ b/frontend/src/router/index.js @@ -0,0 +1,21 @@ +import Vue from 'vue' +import Router from 'vue-router' +import Login from '@/components/Login' +import StudentPage from '@/components/student/StudentPage' + +Vue.use(Router) + +export default new Router({ + routes: [ + { + path: '/', + name: 'grady-login', + component: Login + }, + { + path: '/student/', + name: 'student-page', + component: StudentPage + } + ] +}) diff --git a/frontend/src/store/api.js b/frontend/src/store/api.js new file mode 100644 index 0000000000000000000000000000000000000000..368c09c86195ded2f5c97b1199a26e37c4184190 --- /dev/null +++ b/frontend/src/store/api.js @@ -0,0 +1,7 @@ +import axios from 'axios' + +var ax = axios.create({ + baseURL: 'http://localhost:8000/' +}) + +export default ax diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js new file mode 100644 index 0000000000000000000000000000000000000000..150521a07241ce031fa1bd5454e3ba7a9e9f963f --- /dev/null +++ b/frontend/src/store/store.js @@ -0,0 +1,39 @@ +import Vuex from 'vuex' +import Vue from 'vue' +import ax from './api' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + state: { + token: '', + loggedIn: false, + username: '' + }, + mutations: { + 'LOGIN': function (state, creds) { + state.token = creds.token + state.loggedIn = true + state.username = creds.username + }, + 'LOGOUT': function (state) { + state.token = '' + state.loggedIn = false + } + }, + actions: { + async getToken (store, credentials) { + const response = await ax.post('api-token-auth/', credentials) + store.commit('LOGIN', { + token: response.data.token, + username: credentials.username + }) + ax.defaults.headers.common['Authorization'] = 'JWT ' + response.data.token + }, + logout (store) { + store.commit('LOGOUT') + } + } +}) + +export default store diff --git a/frontend/static/.gitkeep b/frontend/static/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/frontend/test/unit/.eslintrc b/frontend/test/unit/.eslintrc new file mode 100644 index 0000000000000000000000000000000000000000..959a4f4b5764fc6874b1772efd2a3178b5635bca --- /dev/null +++ b/frontend/test/unit/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "mocha": true + }, + "globals": { + "expect": true, + "sinon": true + } +} diff --git a/frontend/test/unit/index.js b/frontend/test/unit/index.js new file mode 100644 index 0000000000000000000000000000000000000000..d0ddfd3846b6da1e934c141b7137655ccd6b13b2 --- /dev/null +++ b/frontend/test/unit/index.js @@ -0,0 +1,14 @@ +import Vue from 'vue' +import 'es6-promise/auto' + +Vue.config.productionTip = false + +// require all test files (files that ends with .spec.js) +const testsContext = require.context('./specs', true, /\.spec$/) +testsContext.keys().forEach(testsContext) + +// require all src files except main.js for coverage. +// you can also change this to match only the subset of files that +// you want coverage for. +const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) +srcContext.keys().forEach(srcContext) diff --git a/frontend/test/unit/karma.conf.js b/frontend/test/unit/karma.conf.js new file mode 100644 index 0000000000000000000000000000000000000000..b77a340f7b3796e08e7f60abee8bded5c26365df --- /dev/null +++ b/frontend/test/unit/karma.conf.js @@ -0,0 +1,29 @@ +// This is a karma config file. For more details see +// http://karma-runner.github.io/0.13/config/configuration-file.html +// we are also using it with karma-webpack +// https://github.com/webpack/karma-webpack + +var webpackConfig = require('../../build/webpack.test.conf') + +module.exports = function (config) { + config.set({ + browsers: ['PhantomJS'], + frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'], + reporters: ['spec', 'coverage'], + files: ['./index.js'], + preprocessors: { + './index.js': ['webpack', 'sourcemap'] + }, + webpack: webpackConfig, + webpackMiddleware: { + noInfo: true + }, + coverageReporter: { + dir: './coverage', + reporters: [ + { type: 'lcov', subdir: '.' }, + { type: 'text-summary' } + ] + } + }) +} diff --git a/frontend/test/unit/specs/SubmissionList.spec.js b/frontend/test/unit/specs/SubmissionList.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..8e855486029934dc781d0058d6bc7e11c7d2ac03 --- /dev/null +++ b/frontend/test/unit/specs/SubmissionList.spec.js @@ -0,0 +1,39 @@ +import Vue from 'vue' +import SubmissionList from '@/components/student/SubmissionList' + +describe('SubmissionList.vue', () => { + it('tests the SubmissionList for students', () => { + const data = [{ + 'type': 'Aufgabe 01', + 'text': 'I dont know the answer.', + 'feedback': 'I am very disappointed.', + 'score': 5, + 'full_score': 14 + }, + { + 'type': 'Aufgabe 01', + 'text': 'A very good solution, indeed', + 'feedback': 'I am still very disappointed.', + 'score': 7, + 'full_score': 10 + }] + + const Constructor = Vue.extend(SubmissionList) + + const comp = new Constructor({ + propsData: { + // Props are passed in "propsData". + submissions: data + } + }).$mount() + + expect(comp.sumScore) + .to.equal(12) + + expect(comp.sumFullScore) + .to.equal(24) + + expect(comp.pointRatio) + .to.equal('50.00') + }) +}) diff --git a/frontend/yarn.lock b/frontend/yarn.lock new file mode 100644 index 0000000000000000000000000000000000000000..a73065fa651effc5cd424b1f4e3d89efebdb00a9 --- /dev/null +++ b/frontend/yarn.lock @@ -0,0 +1,6069 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +accepts@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +accepts@~1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" + dependencies: + mime-types "~2.1.16" + negotiator "0.6.1" + +acorn-dynamic-import@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" + dependencies: + acorn "^4.0.3" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^4.0.3: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + +acorn@^5.0.0, acorn@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" + +after@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv-keywords@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + +ajv@^4.7.0, ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.0.0, ajv@^5.1.0, ajv@^5.1.5: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-html@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arraybuffer.slice@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asn1.js@^4.0.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + +async@1.x, async@^1.4.0, async@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +async@^2.1.2, async@^2.4.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" + dependencies: + lodash "^4.14.0" + +async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + +autoprefixer@^7.1.2: + version "7.1.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.6.tgz#fb933039f74af74a83e71225ce78d9fd58ba84d7" + dependencies: + browserslist "^2.5.1" + caniuse-lite "^1.0.30000748" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.13" + postcss-value-parser "^3.2.3" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +axios@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.0.tgz#7da747916db803f761651d6091d708789b953c6a" + dependencies: + follow-redirects "^1.2.3" + is-buffer "^1.1.5" + +babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.22.1, babel-core@^6.26.0, babel-core@~6: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-eslint@^7.1.1: + version "7.2.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" + dependencies: + babel-code-frame "^6.22.0" + babel-traverse "^6.23.1" + babel-types "^6.23.0" + babylon "^6.17.0" + +babel-generator@^6.18.0, babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-helper-bindify-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-explode-class@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" + dependencies: + babel-helper-bindify-decorators "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-loader@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126" + dependencies: + find-cache-dir "^1.0.0" + loader-utils "^1.0.2" + mkdirp "^0.5.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-istanbul@^4.1.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz#6760cdd977f411d3e175bb064f2bc327d99b2b6e" + dependencies: + find-up "^2.1.0" + istanbul-lib-instrument "^1.7.5" + test-exclude "^4.1.1" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" + dependencies: + babel-helper-explode-class "^6.24.1" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-runtime@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.3.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^2.1.2" + invariant "^2.2.2" + semver "^5.3.0" + +babel-preset-stage-2@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.24.1" + babel-plugin-transform-decorators "^6.24.1" + babel-preset-stage-3 "^6.24.1" + +babel-preset-stage-3@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.24.1" + babel-plugin-transform-async-to-generator "^6.24.1" + babel-plugin-transform-exponentiation-operator "^6.24.1" + babel-plugin-transform-object-rest-spread "^6.22.0" + +babel-register@^6.22.0, babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.17.0, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + +base64-js@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + +base64id@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + dependencies: + callsite "1.0.0" + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + +binary-extensions@^1.0.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" + +blob@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.4.7, bluebird@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + +body-parser@1.18.2, body-parser@^1.16.1: + version "1.18.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.19" + on-finished "~2.3.0" + qs "6.5.1" + raw-body "2.3.2" + type-is "~1.6.15" + +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^0.1.2: + version "0.1.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" + dependencies: + expand-range "^0.1.0" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + +browserslist@^2.1.2, browserslist@^2.5.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.8.0.tgz#27d64028130a2e8585ca96f7c3b7730eff4de493" + dependencies: + caniuse-lite "^1.0.30000758" + electron-to-chromium "^1.3.27" + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + +buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camel-case@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30000760" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000760.tgz#3ea29473eb78a6ccb09f2eb73ac9e1debfec528d" + +caniuse-lite@^1.0.30000748, caniuse-lite@^1.0.30000758: + version "1.0.30000760" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000760.tgz#ec720395742f1c7ec8947fd6dd2604e77a8f98ff" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.1, chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +chokidar@^1.4.1, chokidar@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + dependencies: + chalk "^1.1.3" + +clean-css@4.1.x: + version "4.1.9" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301" + dependencies: + source-map "0.5.x" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.1.0.tgz#f1847b168844d917a671eb9d147e3df497c90d06" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +clone@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + dependencies: + q "^1.1.2" + +coalescy@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/coalescy/-/coalescy-1.0.0.tgz#4b065846b836361ada6c4b4a4abf4bc1cac31bf1" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^1.3.0, color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.0.0, color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + dependencies: + color-name "^1.0.0" + +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + dependencies: + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" + +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + dependencies: + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@^1.1.0, colors@^1.1.2, colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +combine-lists@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" + dependencies: + lodash "^4.5.0" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@2.11.x, commander@^2.9.0, commander@~2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + +component-emitter@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" + +component-emitter@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@1.6.0, concat-stream@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect-history-api-fallback@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.4.0.tgz#3db24f973f4b923b0e82f619ce0df02411ca623d" + +connect@^3.6.0: + version "3.6.5" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.5.tgz#fb8dde7ba0763877d0ec9df9dac0b4b40e72c7da" + dependencies: + debug "2.6.9" + finalhandler "1.0.6" + parseurl "~1.3.2" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +consolidate@^0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.14.5.tgz#5a25047bc76f73072667c8cb52c989888f494c63" + dependencies: + bluebird "^3.1.1" + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +convert-source-map@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +copy-webpack-plugin@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.2.0.tgz#252bb94597f96399d23d7fad355f8d3a661ac096" + dependencies: + bluebird "^3.5.1" + fs-extra "^4.0.2" + glob "^7.1.2" + is-glob "^4.0.0" + loader-utils "^0.2.15" + lodash "^4.3.0" + minimatch "^3.0.4" + node-dir "^0.1.10" + +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.1.0" + os-homedir "^1.0.1" + parse-json "^2.2.0" + require-from-string "^1.1.0" + +create-ecdh@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + ripemd160 "^2.0.0" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.6" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-env@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.1.tgz#b6d8ab97f304c0f71dae7277b75fe424c08dfa74" + dependencies: + cross-spawn "^5.1.0" + is-windows "^1.0.0" + +cross-spawn@^5.0.1, cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +css-color-names@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + +css-loader@^0.28.7: + version "0.28.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b" + dependencies: + babel-code-frame "^6.11.0" + css-selector-tokenizer "^0.7.0" + cssnano ">=2.6.1 <4" + icss-utils "^2.1.0" + loader-utils "^1.0.2" + lodash.camelcase "^4.3.0" + object-assign "^4.0.1" + postcss "^5.0.6" + postcss-modules-extract-imports "^1.0.0" + postcss-modules-local-by-default "^1.0.1" + postcss-modules-scope "^1.0.0" + postcss-modules-values "^1.1.0" + postcss-value-parser "^3.3.0" + source-list-map "^2.0.0" + +css-select@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-selector-tokenizer@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" + dependencies: + cssesc "^0.1.0" + fastparse "^1.1.1" + regexpu-core "^1.0.0" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + +cssesc@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" + +"cssnano@>=2.6.1 <4", cssnano@^3.4.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +dateformat@^1.0.6: + version "1.0.12" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + dependencies: + get-stdin "^4.0.1" + meow "^3.3.0" + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +debug@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" + dependencies: + ms "0.7.2" + +debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + +debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + dependencies: + type-detect "^4.0.0" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@1.1.1, depd@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.2.tgz#71ad5d204bf17a6a6ca8f450c61454066ef461e1" + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +diff@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + +diffie-hellman@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +dom-converter@~0.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b" + dependencies: + utila "~0.3" + +dom-serialize@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domain-browser@^1.1.1: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594" + dependencies: + domelementtype "1" + +domhandler@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" + dependencies: + domelementtype "1" + +domutils@1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485" + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" + dependencies: + dom-serializer "0" + domelementtype "1" + +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +ejs@^2.5.6: + version "2.5.7" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a" + +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.27: + version "1.3.27" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" + +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + +encodeurl@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" + +engine.io-client@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab" + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "2.3.3" + engine.io-parser "1.3.2" + has-cors "1.1.0" + indexof "0.0.1" + parsejson "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + ws "1.1.2" + xmlhttprequest-ssl "1.5.3" + yeast "0.1.2" + +engine.io-parser@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" + dependencies: + after "0.8.2" + arraybuffer.slice "0.0.6" + base64-arraybuffer "0.1.5" + blob "0.0.4" + has-binary "0.1.7" + wtf-8 "1.0.0" + +engine.io@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.3.tgz#8de7f97895d20d39b85f88eeee777b2bd42b13d4" + dependencies: + accepts "1.3.3" + base64id "1.0.0" + cookie "0.3.1" + debug "2.3.3" + engine.io-parser "1.3.2" + ws "1.1.2" + +enhanced-resolve@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + object-assign "^4.0.1" + tapable "^0.2.7" + +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +errno@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" + dependencies: + prr "~0.0.0" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.1.tgz#a3202b8fb03114aa9b40a0e3669e48b2b65a010a" + dependencies: + stackframe "^1.0.3" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.35" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.35.tgz#18ee858ce6a3c45c7d79e91c15fcca9ec568494f" + dependencies: + es6-iterator "~2.0.1" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-promise@^4.0.3, es6-promise@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-standard@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" + +eslint-friendly-formatter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-friendly-formatter/-/eslint-friendly-formatter-3.0.0.tgz#278874435a6c46ec1d94fa0b1ff494e30ef04290" + dependencies: + chalk "^1.0.0" + coalescy "1.0.0" + extend "^3.0.0" + minimist "^1.2.0" + text-table "^0.2.0" + +eslint-import-resolver-node@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" + dependencies: + debug "^2.6.8" + resolve "^1.2.0" + +eslint-loader@^1.7.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-1.9.0.tgz#7e1be9feddca328d3dcfaef1ad49d5beffe83a13" + dependencies: + loader-fs-cache "^1.0.0" + loader-utils "^1.0.2" + object-assign "^4.0.1" + object-hash "^1.1.4" + rimraf "^2.6.1" + +eslint-module-utils@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-html@^3.0.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-3.2.2.tgz#ef7093621d3a93de3206fd1f92f347ea9a1a4dfa" + dependencies: + htmlparser2 "^3.8.2" + semver "^5.4.1" + +eslint-plugin-import@^2.7.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.6.8" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + read-pkg-up "^2.0.0" + +eslint-plugin-node@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz#80df3253c4d7901045ec87fa660a284e32bdca29" + dependencies: + ignore "^3.3.6" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "5.3.0" + +eslint-plugin-promise@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75" + +eslint-plugin-standard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint@^3.19.0: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.1.tgz#0c988b8ab46db53100a1954ae4ba995ddd27d87e" + dependencies: + acorn "^5.1.1" + acorn-jsx "^3.0.0" + +esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +eventemitter3@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + +events@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +eventsource-polyfill@^0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/eventsource-polyfill/-/eventsource-polyfill-0.9.6.tgz#10e0d187f111b167f28fdab918843ce7d818f13c" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-braces@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" + dependencies: + array-slice "^0.2.3" + array-unique "^0.2.1" + braces "^0.1.2" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" + dependencies: + is-number "^0.1.1" + repeat-string "^0.2.2" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +express@^4.14.1, express@^4.15.2: + version "4.16.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" + dependencies: + accepts "~1.3.4" + array-flatten "1.1.1" + body-parser "1.18.2" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.1" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.0" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.2" + qs "6.5.1" + range-parser "~1.2.0" + safe-buffer "5.1.1" + send "0.16.1" + serve-static "1.13.1" + setprototypeof "1.1.0" + statuses "~1.3.1" + type-is "~1.6.15" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extract-text-webpack-plugin@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7" + dependencies: + async "^2.4.1" + loader-utils "^1.1.0" + schema-utils "^0.3.0" + webpack-sources "^1.0.1" + +extract-zip@^1.6.5: + version "1.6.6" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" + dependencies: + concat-stream "1.6.0" + debug "2.6.9" + mkdirp "0.5.0" + yauzl "2.4.1" + +extsprintf@1.3.0, extsprintf@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fastparse@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" + +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + dependencies: + pend "~1.2.0" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +file-loader@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.5.tgz#91c25b6b6fbe56dae99f10a425fd64933b5c9daa" + dependencies: + loader-utils "^1.0.2" + schema-utils "^0.3.0" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +filesize@^3.5.9: + version "3.5.11" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +finalhandler@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.6.tgz#007aea33d1a4d3e42017f624848ad58d212f814f" + dependencies: + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" + unpipe "~1.0.0" + +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" + dependencies: + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" + unpipe "~1.0.0" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-cache-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" + dependencies: + commondir "^1.0.1" + make-dir "^1.0.0" + pkg-dir "^2.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + +follow-redirects@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.5.tgz#ffd3e14cbdd5eaa72f61b6368c1f68516c2a26cc" + dependencies: + debug "^2.6.9" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +formatio@1.2.0, formatio@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" + dependencies: + samsam "1.x" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +friendly-errors-webpack-plugin@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.6.1.tgz#e32781c4722f546a06a9b5d7a7cfa28520375d70" + dependencies: + chalk "^1.1.3" + error-stack-parser "^2.0.0" + string-length "^1.0.1" + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-extra@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.36" + +fstream-ignore@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.14.0, globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +gzip-size@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520" + dependencies: + duplexer "^0.1.1" + +handlebars@^4.0.1: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-binary@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" + dependencies: + isarray "0.0.1" + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hash-base@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" + dependencies: + inherits "^2.0.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash-sum@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hasha@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-2.2.0.tgz#78d7cbfc1e6d66303fe79837365984517b2f6ee1" + dependencies: + is-stream "^1.0.1" + pinkie-promise "^2.0.0" + +hawk@3.1.3, hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +he@1.1.1, he@1.1.x, he@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + +html-comment-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" + +html-entities@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" + +html-minifier@^3.2.3: + version "3.5.6" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.6.tgz#7e4e661a09999599c7d8e8a2b8d7fb7430bb5c3e" + dependencies: + camel-case "3.0.x" + clean-css "4.1.x" + commander "2.11.x" + he "1.1.x" + ncname "1.0.x" + param-case "2.1.x" + relateurl "0.2.x" + uglify-js "3.1.x" + +html-webpack-plugin@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz#7f9c421b7ea91ec460f56527d78df484ee7537d5" + dependencies: + bluebird "^3.4.7" + html-minifier "^3.2.3" + loader-utils "^0.2.16" + lodash "^4.17.3" + pretty-error "^2.0.2" + toposort "^1.0.0" + +htmlparser2@^3.8.2: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +htmlparser2@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe" + dependencies: + domelementtype "1" + domhandler "2.1" + domutils "1.1" + readable-stream "1.0" + +http-errors@1.6.2, http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-proxy-middleware@^0.17.3: + version "0.17.4" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833" + dependencies: + http-proxy "^1.16.2" + is-glob "^3.1.0" + lodash "^4.17.2" + micromatch "^2.3.11" + +http-proxy@^1.13.0, http-proxy@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" + dependencies: + eventemitter3 "1.x.x" + requires-port "1.x.x" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" + +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + +icss-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" + dependencies: + postcss "^6.0.1" + +ieee754@^1.1.4: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + +ignore@^3.2.0, ignore@^3.3.6: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +inject-loader@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/inject-loader/-/inject-loader-3.0.1.tgz#844a4596150cf6b864c2f79806d40a2caee4c2c7" + dependencies: + babel-core "~6" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0" + +invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ipaddr.js@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + +is-my-json-valid@^2.10.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + dependencies: + html-comment-regex "^1.1.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isbinaryfile@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" + +istanbul-lib-instrument@^1.7.5: + version "1.9.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.18.0" + istanbul-lib-coverage "^1.1.1" + semver "^5.3.0" + +istanbul@^0.4.0: + version "0.4.5" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +js-base64@^2.1.9: + version "2.3.2" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-loader@^0.5.4: + version "0.5.7" + resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +json5@^0.5.0, json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +just-extend@^1.1.26: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + +karma-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-1.1.1.tgz#5aff8b39cf6994dc22de4c84362c76001b637cf6" + dependencies: + dateformat "^1.0.6" + istanbul "^0.4.0" + lodash "^3.8.0" + minimatch "^3.0.0" + source-map "^0.5.1" + +karma-mocha@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-1.3.0.tgz#eeaac7ffc0e201eb63c467440d2b69c7cf3778bf" + dependencies: + minimist "1.2.0" + +karma-phantomjs-launcher@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz#d23ca34801bda9863ad318e3bb4bd4062b13acd2" + dependencies: + lodash "^4.0.1" + phantomjs-prebuilt "^2.1.7" + +karma-phantomjs-shim@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/karma-phantomjs-shim/-/karma-phantomjs-shim-1.5.0.tgz#e8db65883480f0dbd184cc961d39c64511742200" + +karma-sinon-chai@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/karma-sinon-chai/-/karma-sinon-chai-1.3.3.tgz#a597e5b4a1369fe7b3d7d76c09ed2061a38e747f" + dependencies: + lolex "^1.6.0" + +karma-sourcemap-loader@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" + dependencies: + graceful-fs "^4.1.2" + +karma-spec-reporter@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.31.tgz#4830dc7148a155c7d7a186e632339a0d80fadec3" + dependencies: + colors "^1.1.2" + +karma-webpack@^2.0.2: + version "2.0.5" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-2.0.5.tgz#4f56887e32cf4f9583391c2388415de06af06efd" + dependencies: + async "~0.9.0" + loader-utils "^0.2.5" + lodash "^3.8.0" + source-map "^0.1.41" + webpack-dev-middleware "^1.0.11" + +karma@^1.4.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/karma/-/karma-1.7.1.tgz#85cc08e9e0a22d7ce9cca37c4a1be824f6a2b1ae" + dependencies: + bluebird "^3.3.0" + body-parser "^1.16.1" + chokidar "^1.4.1" + colors "^1.1.0" + combine-lists "^1.0.0" + connect "^3.6.0" + core-js "^2.2.0" + di "^0.0.1" + dom-serialize "^2.2.0" + expand-braces "^0.1.1" + glob "^7.1.1" + graceful-fs "^4.1.2" + http-proxy "^1.13.0" + isbinaryfile "^3.0.0" + lodash "^3.8.0" + log4js "^0.6.31" + mime "^1.3.4" + minimatch "^3.0.2" + optimist "^0.6.1" + qjobs "^1.1.4" + range-parser "^1.2.0" + rimraf "^2.6.0" + safe-buffer "^5.0.1" + socket.io "1.7.3" + source-map "^0.5.3" + tmp "0.0.31" + useragent "^2.1.12" + +kew@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + optionalDependencies: + graceful-fs "^4.1.9" + +last-call-webpack-plugin@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-2.1.2.tgz#ad80c6e310998294d2ed2180a68e9589e4768c44" + dependencies: + lodash "^4.17.4" + webpack-sources "^1.0.1" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +loader-fs-cache@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz#56e0bf08bd9708b26a765b68509840c8dec9fdbc" + dependencies: + find-cache-dir "^0.1.1" + mkdirp "0.5.1" + +loader-runner@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" + +loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.5: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +loader-utils@^1.0.2, loader-utils@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + +lodash@^3.8.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +lodash@^4.0.0, lodash@^4.0.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +log4js@^0.6.31: + version "0.6.38" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" + dependencies: + readable-stream "~1.0.2" + semver "~4.3.3" + +lolex@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" + +lolex@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.0.tgz#d6bad0f0aa5caebffcfebb09fb2caa89baaff51c" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + +lru-cache@2.2.x: + version "2.2.4" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" + +lru-cache@^4.0.1, lru-cache@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +macaddress@^0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" + +make-dir@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" + dependencies: + pify "^3.0.0" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" + +md5.js@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +meow@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +micromatch@^2.1.5, micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime@1.3.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" + +mime@1.4.1, mime@^1.3.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +minimalistic-assert@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@1.2.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + +mkdirp@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + dependencies: + minimist "0.0.8" + +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^3.2.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.8" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + he "1.1.1" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +nan@^2.3.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +ncname@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ncname/-/ncname-1.0.0.tgz#5b57ad18b1ca092864ef62b0b1ed8194f383b71c" + dependencies: + xml-char-classes "^1.0.0" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +nise@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53" + dependencies: + formatio "^1.2.0" + just-extend "^1.1.26" + lolex "^1.6.0" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + dependencies: + lower-case "^1.1.1" + +node-dir@^0.1.10: + version "0.1.17" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" + dependencies: + minimatch "^3.0.2" + +node-libs-browser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.1.4" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "0.0.1" + os-browserify "^0.2.0" + path-browserify "0.0.0" + process "^0.11.0" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.0.5" + stream-browserify "^2.0.1" + stream-http "^2.3.1" + string_decoder "^0.10.25" + timers-browserify "^2.0.2" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-pre-gyp@^0.6.36: + version "0.6.39" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" + dependencies: + detect-libc "^1.0.2" + hawk "3.1.3" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + +normalize-url@^1.4.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + +object-hash@^1.1.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.2.0.tgz#e96af0e96981996a1d47f88ead8f74f1ebc4422b" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@1.x, once@^1.3.0, once@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opener@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" + +opn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" + dependencies: + is-wsl "^1.1.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optimize-css-assets-webpack-plugin@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-3.2.0.tgz#09a40c4cefde1dd0142444a873c56aa29eb18e6f" + dependencies: + cssnano "^3.4.0" + last-call-webpack-plugin "^2.1.2" + +optionator@^0.8.1, optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + +ora@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a" + dependencies: + chalk "^1.1.1" + cli-cursor "^2.1.0" + cli-spinners "^1.0.0" + log-symbols "^1.0.2" + +os-browserify@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +param-case@2.1.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + dependencies: + no-case "^2.2.0" + +parse-asn1@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parsejson@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" + dependencies: + better-assert "~1.0.0" + +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + dependencies: + better-assert "~1.0.0" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + +pbkdf2@^3.0.3: + version "3.0.14" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +phantomjs-prebuilt@^2.1.14, phantomjs-prebuilt@^2.1.7: + version "2.1.16" + resolved "https://registry.yarnpkg.com/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz#efd212a4a3966d3647684ea8ba788549be2aefef" + dependencies: + es6-promise "^4.0.3" + extract-zip "^1.6.5" + fs-extra "^1.0.0" + hasha "^2.2.0" + kew "^0.7.0" + progress "^1.1.8" + request "^2.81.0" + request-progress "^2.0.1" + which "^1.2.10" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + dependencies: + find-up "^2.1.0" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +portfinder@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9" + dependencies: + async "^1.5.2" + debug "^2.2.0" + mkdirp "0.5.x" + +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + dependencies: + postcss "^5.0.14" + +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + dependencies: + postcss "^5.0.4" + +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + dependencies: + postcss "^5.0.14" + +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + dependencies: + postcss "^5.0.16" + +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + +postcss-filter-plugins@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c" + dependencies: + postcss "^5.0.4" + uniqid "^4.0.0" + +postcss-load-config@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + postcss-load-options "^1.2.0" + postcss-load-plugins "^2.3.0" + +postcss-load-options@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + +postcss-load-plugins@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" + dependencies: + cosmiconfig "^2.1.1" + object-assign "^4.1.0" + +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + dependencies: + postcss "^5.0.4" + +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-modules-extract-imports@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85" + dependencies: + postcss "^6.0.1" + +postcss-modules-local-by-default@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-scope@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-values@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" + dependencies: + icss-replace-symbols "^1.1.0" + postcss "^6.0.1" + +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + dependencies: + postcss "^5.0.5" + +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + dependencies: + postcss "^5.0.4" + +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1, postcss@^6.0.13, postcss@^6.0.8: + version "6.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^4.4.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +prettier@^1.7.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.1.tgz#91064d778c08c85ac1cbe6b23195c34310d039f9" + +pretty-error@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" + dependencies: + renderkid "^2.0.1" + utila "~0.4" + +private@^0.1.6, private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process@^0.11.0: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +proxy-addr@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.5.2" + +prr@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +public-encrypt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +qjobs@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" + +qs@6.5.1, qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0, querystring@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + +rc@^1.1.7: + version "1.2.2" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@1.0, readable-stream@~1.0.2: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-function-call@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" + dependencies: + balanced-match "^0.4.2" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regexpu-core@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +relateurl@0.2.x: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +renderkid@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.1.tgz#898cabfc8bede4b7b91135a3ffd323e58c0db319" + dependencies: + css-select "^1.1.0" + dom-converter "~0.1" + htmlparser2 "~3.3.0" + strip-ansi "^3.0.0" + utila "~0.3" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request-progress@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-2.0.1.tgz#5d36bb57961c673aa5b788dbc8141fdf23b44e08" + dependencies: + throttleit "^1.0.0" + +request@2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@^2.81.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +requires-port@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.6, resolve@^1.2.0, resolve@^1.3.3, resolve@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" + dependencies: + hash-base "^2.0.0" + inherits "^2.0.1" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +samsam@1.x: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" + +sax@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +schema-utils@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" + dependencies: + ajv "^5.0.0" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + +semver@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +semver@~4.3.3: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +send@0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" + dependencies: + debug "2.6.9" + depd "~1.1.1" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.1" + +serve-static@1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.1" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.9" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shelljs@^0.7.5, shelljs@^0.7.6: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +sinon-chai@^2.8.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.14.0.tgz#da7dd4cc83cd6a260b67cca0f7a9fdae26a1205d" + +sinon@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.2.tgz#65610521d926fb53742dd84cd599f0b89a82f440" + dependencies: + diff "^3.1.0" + formatio "1.2.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^4.4.0" + type-detect "^4.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +socket.io-adapter@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" + dependencies: + debug "2.3.3" + socket.io-parser "2.3.1" + +socket.io-client@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.3.tgz#b30e86aa10d5ef3546601c09cde4765e381da377" + dependencies: + backo2 "1.0.2" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "2.3.3" + engine.io-client "1.8.3" + has-binary "0.1.7" + indexof "0.0.1" + object-component "0.0.3" + parseuri "0.0.5" + socket.io-parser "2.3.1" + to-array "0.1.4" + +socket.io-parser@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" + dependencies: + component-emitter "1.1.2" + debug "2.2.0" + isarray "0.0.1" + json3 "3.3.2" + +socket.io@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.3.tgz#b8af9caba00949e568e369f1327ea9be9ea2461b" + dependencies: + debug "2.3.3" + engine.io "1.8.3" + has-binary "0.1.7" + object-assign "4.1.0" + socket.io-adapter "0.5.0" + socket.io-client "1.7.3" + socket.io-parser "2.3.1" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + dependencies: + is-plain-obj "^1.0.0" + +source-list-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.1.41: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + dependencies: + amdefine ">=0.0.4" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stackframe@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" + +"statuses@>= 1.3.1 < 2": + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-http@^2.3.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.2.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + +string-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" + dependencies: + strip-ansi "^3.0.0" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^0.10.25, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4, stringstream@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.0, supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tapable@^0.2.7: + version "0.2.8" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" + +tar-pack@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +test-exclude@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" + dependencies: + arrify "^1.0.1" + micromatch "^2.3.11" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + +text-table@^0.2.0, text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +throttleit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +time-stamp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" + +timers-browserify@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" + dependencies: + setimmediate "^1.0.4" + +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + +tmp@0.0.x: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +toposort@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" + +type-is@~1.6.15: + version "1.6.15" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.15" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@3.1.x: + version "3.1.8" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.8.tgz#780d08b4f6782fe36ea5484d952362eddaf1d7b8" + dependencies: + commander "~2.11.0" + source-map "~0.6.1" + +uglify-js@^2.6, uglify-js@^2.8.29: + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +uglifyjs-webpack-plugin@^0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" + dependencies: + source-map "^0.5.6" + uglify-js "^2.8.29" + webpack-sources "^1.0.1" + +uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + +ultron@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + +uniqid@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1" + dependencies: + macaddress "^0.2.8" + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + +universalify@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + +url-loader@^0.5.8: + version "0.5.9" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295" + dependencies: + loader-utils "^1.0.2" + mime "1.3.x" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +useragent@^2.1.12: + version "2.2.1" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" + dependencies: + lru-cache "2.2.x" + tmp "0.0.x" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util@0.10.3, util@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +utila@~0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.3.3.tgz#d7e8e7d7e309107092b05f8d9688824d633a4226" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + +uuid@^3.0.0, uuid@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +vendors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + +vue-hot-reload-api@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.2.3.tgz#43c8e5506d65a271d2571936d77253019fd3eb17" + +vue-loader@^13.3.0: + version "13.5.0" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.5.0.tgz#52f7b3790a267eff80012b77ea187a54586dd5d4" + dependencies: + consolidate "^0.14.0" + hash-sum "^1.0.2" + loader-utils "^1.1.0" + lru-cache "^4.1.1" + postcss "^6.0.8" + postcss-load-config "^1.1.0" + postcss-selector-parser "^2.0.0" + prettier "^1.7.0" + resolve "^1.4.0" + source-map "^0.6.1" + vue-hot-reload-api "^2.2.0" + vue-style-loader "^3.0.0" + vue-template-es2015-compiler "^1.6.0" + +vue-router@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9" + +vue-style-loader@^3.0.0, vue-style-loader@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-3.0.3.tgz#623658f81506aef9d121cdc113a4f5c9cac32df7" + dependencies: + hash-sum "^1.0.2" + loader-utils "^1.0.2" + +vue-template-compiler@^2.5.2: + version "2.5.3" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.3.tgz#ab631b0694e211a6aaf0d800102b37836aae36a4" + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + +vue-template-es2015-compiler@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" + +vue@^2.5.2: + version "2.5.3" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.3.tgz#e1a3b1f49b6e93e574ce040b95cbc873912fecc1" + +vuetify@^0.16.9: + version "0.16.9" + resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-0.16.9.tgz#fd61f219e4a40d7afe5e24a803df5658a40b38e4" + +vuex@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.1.tgz#e761352ebe0af537d4bb755a9b9dc4be3df7efd2" + +watchpack@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" + dependencies: + async "^2.1.2" + chokidar "^1.7.0" + graceful-fs "^4.1.2" + +webpack-bundle-analyzer@^2.9.0: + version "2.9.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.9.1.tgz#c2c8e03e8e5768ed288b39ae9e27a8b8d7b9d476" + dependencies: + acorn "^5.1.1" + chalk "^1.1.3" + commander "^2.9.0" + ejs "^2.5.6" + express "^4.15.2" + filesize "^3.5.9" + gzip-size "^3.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + opener "^1.4.3" + ws "^3.3.1" + +webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz#d34efefb2edda7e1d3b5dbe07289513219651709" + dependencies: + memory-fs "~0.4.1" + mime "^1.3.4" + path-is-absolute "^1.0.0" + range-parser "^1.0.3" + time-stamp "^2.0.0" + +webpack-hot-middleware@^2.18.2: + version "2.20.0" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.20.0.tgz#cb896d837758b6408fe0afeeafdc0e5316b15319" + dependencies: + ansi-html "0.0.7" + html-entities "^1.2.0" + querystring "^0.2.0" + strip-ansi "^3.0.0" + +webpack-merge@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.1.tgz#f1197a0a973e69c6fbeeb6d658219aa8c0c13555" + dependencies: + lodash "^4.17.4" + +webpack-sources@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.2.tgz#d0148ec083b3b5ccef1035a6b3ec16442983b27a" + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^3.6.0: + version "3.8.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.8.1.tgz#b16968a81100abe61608b0153c9159ef8bb2bd83" + dependencies: + acorn "^5.0.0" + acorn-dynamic-import "^2.0.0" + ajv "^5.1.5" + ajv-keywords "^2.0.0" + async "^2.1.2" + enhanced-resolve "^3.4.0" + escope "^3.6.0" + interpret "^1.0.0" + json-loader "^0.5.4" + json5 "^0.5.1" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + mkdirp "~0.5.0" + node-libs-browser "^2.0.0" + source-map "^0.5.3" + supports-color "^4.2.1" + tapable "^0.2.7" + uglifyjs-webpack-plugin "^0.4.6" + watchpack "^1.4.0" + webpack-sources "^1.0.1" + yargs "^8.0.2" + +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@^1.1.1, which@^1.2.10, which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +ws@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +ws@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.1.tgz#d97e34dee06a1190c61ac1e95f43cb60b78cf939" + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +wtf-8@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" + +xml-char-classes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d" + +xmlhttprequest-ssl@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" + +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + dependencies: + fd-slicer "~1.0.1" + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" diff --git a/package.json b/package.json deleted file mode 100644 index 6e3d256059fccec3c5191f3df873fc61a8a3819a..0000000000000000000000000000000000000000 --- a/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "grady", - "version": "0.4.2", - "description": "A new way to correct programming exams", - "main": "index.js", - "repository": "https://gitlab.gwdg.de/j.michal/grady.git", - "author": "Jan Maximilian Michal", - "license": "MIT", - "dependencies": { - "ace-editor-builds": "^1.2.4", - "bootstrap": "4.0.0-beta.2", - "datatables.net": "^1.10.15", - "datatables.net-bs4": "^1.10.15", - "popper.js": "^1.12.3" - } -} diff --git a/pre-commit-scripts/prospector.sh b/pre-commit-scripts/prospector.sh new file mode 100755 index 0000000000000000000000000000000000000000..dd41b303bcb966282958a05885d2e9344ba84eb4 --- /dev/null +++ b/pre-commit-scripts/prospector.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +cd backend +unset GIT_DIR + +diff_files="$(git diff --cached --name-only --relative --diff-filter=AM)" +if [ -n "$diff_files" ]; then + prospector --uses django $diff_files +else + exit 0 +fi \ No newline at end of file