From b754d841494c099969e91c72a43ff27452f2e88b Mon Sep 17 00:00:00 2001 From: devfake Date: Mon, 10 Oct 2016 10:57:39 +0200 Subject: [PATCH] Init new version --- .gitattributes | 3 + .gitignore | 12 +- README.md | 61 +- backend/.env.example | 18 + backend/app/Console/Commands/DB.php | 49 + backend/app/Console/Commands/Init.php | 64 + backend/app/Console/Commands/Sync.php | 32 + backend/app/Console/Kernel.php | 42 + backend/app/Exceptions/Handler.php | 65 + backend/app/Http/Controllers/Controller.php | 13 + .../app/Http/Controllers/ItemController.php | 152 + .../app/Http/Controllers/TMDBController.php | 21 + .../app/Http/Controllers/UserController.php | 50 + backend/app/Http/Kernel.php | 56 + .../app/Http/Middleware/EncryptCookies.php | 17 + .../Middleware/RedirectIfAuthenticated.php | 26 + .../app/Http/Middleware/VerifyCsrfToken.php | 17 + backend/app/Item.php | 24 + backend/app/Providers/AppServiceProvider.php | 28 + backend/app/Providers/AuthServiceProvider.php | 30 + .../Providers/BroadcastServiceProvider.php | 26 + .../app/Providers/EventServiceProvider.php | 32 + .../app/Providers/RouteServiceProvider.php | 79 + backend/app/Services/TMDB.php | 70 + backend/app/User.php | 16 + backend/artisan | 51 + backend/bootstrap/app.php | 55 + backend/bootstrap/autoload.php | 34 + backend/bootstrap/cache/.gitignore | 2 + backend/composer.json | 53 + backend/composer.lock | 3786 +++++++ backend/config/app.php | 238 + backend/config/auth.php | 102 + backend/config/broadcasting.php | 58 + backend/config/cache.php | 91 + backend/config/compile.php | 35 + backend/config/database.php | 121 + backend/config/filesystems.php | 67 + backend/config/mail.php | 115 + backend/config/queue.php | 85 + backend/config/scout.php | 83 + backend/config/services.php | 38 + backend/config/session.php | 179 + backend/config/view.php | 33 + backend/database/.gitignore | 1 + backend/database/factories/ModelFactory.php | 23 + .../2016_08_01_121249_create_items_table.php | 36 + .../2016_08_05_132344_create_users_table.php | 33 + backend/database/seeds/.gitkeep | 1 + backend/database/seeds/DatabaseSeeder.php | 16 + backend/phpunit.xml | 27 + backend/routes/api.php | 0 backend/routes/console.php | 0 backend/routes/web.php | 21 + backend/server.php | 21 + backend/storage/app/.gitignore | 3 + backend/storage/app/public/.gitignore | 2 + backend/storage/framework/.gitignore | 8 + backend/storage/framework/cache/.gitignore | 2 + backend/storage/framework/sessions/.gitignore | 2 + backend/storage/framework/views/.gitignore | 2 + backend/storage/logs/.gitignore | 2 + backend/tests/ExampleTest.php | 19 + backend/tests/TestCase.php | 25 + client/.babelrc | 5 + client/app/app.js | 45 + client/app/components/Content/Content.vue | 58 + client/app/components/Content/Item.vue | 109 + .../app/components/Content/SearchContent.vue | 82 + client/app/components/Content/Settings.vue | 32 + client/app/components/Footer.vue | 41 + client/app/components/Header.vue | 62 + client/app/components/Login.vue | 55 + client/app/components/Search.vue | 70 + client/app/config.js | 18 + client/app/helper.js | 23 + client/app/routes.js | 22 + client/app/store/actions.js | 45 + client/app/store/index.js | 21 + client/app/store/mutations.js | 35 + client/app/store/types.js | 8 + client/gulpfile.js | 19 + client/package.json | 34 + client/resources/app.blade.php | 37 + client/resources/sass/_base.scss | 46 + client/resources/sass/_misc.scss | 153 + client/resources/sass/_normalize.scss | 419 + client/resources/sass/_shake.scss | 129 + client/resources/sass/_sprite.scss | 96 + client/resources/sass/app.scss | 13 + .../resources/sass/components/_content.scss | 262 + client/resources/sass/components/_footer.scss | 61 + client/resources/sass/components/_header.scss | 92 + client/resources/sass/components/_login.scss | 61 + client/resources/sass/components/_search.scss | 104 + client/webpack.config.js | 70 + public/.htaccess | 20 + public/assets/app.css | 1555 +++ public/assets/app.js | 6225 +++++++++++ public/assets/favicon.ico | Bin 0 -> 1406 bytes public/assets/img/add.png | Bin 0 -> 151 bytes public/assets/img/algolia-dark.png | Bin 0 -> 1327 bytes public/assets/img/algolia-white.png | Bin 0 -> 1432 bytes public/assets/img/github.png | Bin 0 -> 506 bytes public/assets/img/logo-login.png | Bin 0 -> 1552 bytes public/assets/img/logo-small.png | Bin 0 -> 807 bytes public/assets/img/logo.png | Bin 0 -> 834 bytes public/assets/img/rating-1.png | Bin 0 -> 584 bytes public/assets/img/rating-2.png | Bin 0 -> 589 bytes public/assets/img/rating-3.png | Bin 0 -> 581 bytes public/assets/img/remove.png | Bin 0 -> 368 bytes public/assets/img/search-dark.png | Bin 0 -> 287 bytes public/assets/img/search.png | Bin 0 -> 311 bytes public/assets/img/sort-star.png | Bin 0 -> 492 bytes public/assets/img/sort-time.png | Bin 0 -> 453 bytes public/assets/img/tmdb.png | Bin 0 -> 1202 bytes public/assets/vendor.js | 9576 +++++++++++++++++ public/index.php | 58 + 118 files changed, 26229 insertions(+), 5 deletions(-) create mode 100644 .gitattributes create mode 100644 backend/.env.example create mode 100644 backend/app/Console/Commands/DB.php create mode 100644 backend/app/Console/Commands/Init.php create mode 100644 backend/app/Console/Commands/Sync.php create mode 100644 backend/app/Console/Kernel.php create mode 100644 backend/app/Exceptions/Handler.php create mode 100644 backend/app/Http/Controllers/Controller.php create mode 100644 backend/app/Http/Controllers/ItemController.php create mode 100644 backend/app/Http/Controllers/TMDBController.php create mode 100644 backend/app/Http/Controllers/UserController.php create mode 100644 backend/app/Http/Kernel.php create mode 100644 backend/app/Http/Middleware/EncryptCookies.php create mode 100644 backend/app/Http/Middleware/RedirectIfAuthenticated.php create mode 100644 backend/app/Http/Middleware/VerifyCsrfToken.php create mode 100644 backend/app/Item.php create mode 100644 backend/app/Providers/AppServiceProvider.php create mode 100644 backend/app/Providers/AuthServiceProvider.php create mode 100644 backend/app/Providers/BroadcastServiceProvider.php create mode 100644 backend/app/Providers/EventServiceProvider.php create mode 100644 backend/app/Providers/RouteServiceProvider.php create mode 100644 backend/app/Services/TMDB.php create mode 100644 backend/app/User.php create mode 100644 backend/artisan create mode 100644 backend/bootstrap/app.php create mode 100644 backend/bootstrap/autoload.php create mode 100644 backend/bootstrap/cache/.gitignore create mode 100644 backend/composer.json create mode 100644 backend/composer.lock create mode 100644 backend/config/app.php create mode 100644 backend/config/auth.php create mode 100644 backend/config/broadcasting.php create mode 100644 backend/config/cache.php create mode 100644 backend/config/compile.php create mode 100644 backend/config/database.php create mode 100644 backend/config/filesystems.php create mode 100644 backend/config/mail.php create mode 100644 backend/config/queue.php create mode 100644 backend/config/scout.php create mode 100644 backend/config/services.php create mode 100644 backend/config/session.php create mode 100644 backend/config/view.php create mode 100644 backend/database/.gitignore create mode 100644 backend/database/factories/ModelFactory.php create mode 100644 backend/database/migrations/2016_08_01_121249_create_items_table.php create mode 100644 backend/database/migrations/2016_08_05_132344_create_users_table.php create mode 100644 backend/database/seeds/.gitkeep create mode 100644 backend/database/seeds/DatabaseSeeder.php create mode 100644 backend/phpunit.xml create mode 100644 backend/routes/api.php create mode 100644 backend/routes/console.php create mode 100644 backend/routes/web.php create mode 100644 backend/server.php create mode 100644 backend/storage/app/.gitignore create mode 100644 backend/storage/app/public/.gitignore create mode 100644 backend/storage/framework/.gitignore create mode 100644 backend/storage/framework/cache/.gitignore create mode 100644 backend/storage/framework/sessions/.gitignore create mode 100644 backend/storage/framework/views/.gitignore create mode 100644 backend/storage/logs/.gitignore create mode 100644 backend/tests/ExampleTest.php create mode 100644 backend/tests/TestCase.php create mode 100644 client/.babelrc create mode 100644 client/app/app.js create mode 100644 client/app/components/Content/Content.vue create mode 100644 client/app/components/Content/Item.vue create mode 100644 client/app/components/Content/SearchContent.vue create mode 100644 client/app/components/Content/Settings.vue create mode 100644 client/app/components/Footer.vue create mode 100644 client/app/components/Header.vue create mode 100644 client/app/components/Login.vue create mode 100644 client/app/components/Search.vue create mode 100644 client/app/config.js create mode 100644 client/app/helper.js create mode 100644 client/app/routes.js create mode 100644 client/app/store/actions.js create mode 100644 client/app/store/index.js create mode 100644 client/app/store/mutations.js create mode 100644 client/app/store/types.js create mode 100644 client/gulpfile.js create mode 100644 client/package.json create mode 100644 client/resources/app.blade.php create mode 100644 client/resources/sass/_base.scss create mode 100644 client/resources/sass/_misc.scss create mode 100644 client/resources/sass/_normalize.scss create mode 100644 client/resources/sass/_shake.scss create mode 100644 client/resources/sass/_sprite.scss create mode 100644 client/resources/sass/app.scss create mode 100644 client/resources/sass/components/_content.scss create mode 100644 client/resources/sass/components/_footer.scss create mode 100644 client/resources/sass/components/_header.scss create mode 100644 client/resources/sass/components/_login.scss create mode 100644 client/resources/sass/components/_search.scss create mode 100644 client/webpack.config.js create mode 100644 public/.htaccess create mode 100644 public/assets/app.css create mode 100644 public/assets/app.js create mode 100644 public/assets/favicon.ico create mode 100644 public/assets/img/add.png create mode 100644 public/assets/img/algolia-dark.png create mode 100644 public/assets/img/algolia-white.png create mode 100644 public/assets/img/github.png create mode 100644 public/assets/img/logo-login.png create mode 100644 public/assets/img/logo-small.png create mode 100644 public/assets/img/logo.png create mode 100644 public/assets/img/rating-1.png create mode 100644 public/assets/img/rating-2.png create mode 100644 public/assets/img/rating-3.png create mode 100644 public/assets/img/remove.png create mode 100644 public/assets/img/search-dark.png create mode 100644 public/assets/img/search.png create mode 100644 public/assets/img/sort-star.png create mode 100644 public/assets/img/sort-time.png create mode 100644 public/assets/img/tmdb.png create mode 100644 public/assets/vendor.js create mode 100644 public/index.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a8763f8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto +*.css linguist-vendored +*.scss linguist-vendored diff --git a/.gitignore b/.gitignore index 57a9fed..f0b4392 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ -.idea -.env - -/backend/vendor /client/node_modules +/backend/vendor +/.idea +Homestead.json +Homestead.yaml +/backend/.env + +*/.DS_Store +/public/assets/poster/*.jpg \ No newline at end of file diff --git a/README.md b/README.md index d2067ae..f6af360 100644 --- a/README.md +++ b/README.md @@ -1 +1,60 @@ -New version is coming soon \ No newline at end of file +![flox](http://80.240.132.120/flox-demo/public/assets/img/dark.jpg) + +Flox +=============== +Flox is a self hosted Movie watch list. It's build on top of PHP (Laravel), MySQL and Vue.js and uses [The Movie Database](https://www.themoviedb.org/) API. +The rating based on an 3-Point system for `good`, `medium` and `bad`. + +[Try live demo](http://80.240.132.120/flox-demo/public/) and [login](http://80.240.132.120/flox-demo/public/login) with `demo / demo` to add new movies or change ratings. + +### Requirements + +* PHP >=5.6.4 +* [Composer](https://getcomposer.org/) +* [The Movie Database](https://www.themoviedb.org/) Account for the [API-Key](https://www.themoviedb.org/faq/api) + +### Install + +* Download Flox and `cd` into `backend` and run +```bash +composer install +php artisan flox:init # Enter here your database credentials +php artisan flox:db # Running migrations and enter your admin credentials for the site +``` +* Enter your TMDB API-Key in `backend/.env` +* Set your `CLIENT_URI` in `backend/.env`. If you use something like XAMPP or MAMP, the CLIENT_URI should be `/flox/public`. If you use something like Homestead, the CLIENT_URI should be `/`. + +### Alternative Language + +All movie titles are in english by default. You can check if TMDB has an alternative title by setting `ALTERNATIVE_LANGUAGE` in `backend/.env`. +The most commons are `DE`, `IT`, `FR`, `ES` and `RU`. + +### Better Search + +You can use [Laravel Scout](https://laravel.com/docs/master/scout) for better search results with typos. Something like `findg nemo`. +Add your driver and API-Keys in `backend/.env` and uncomment `use Searchable;` in `backend/app/Item.php` on line 11. + +To sync your own movie list with your Laravel Scout driver, run `php artisan flox:sync` (If you using Laravel Scout later). + +[Algolia](https://www.algolia.com/) is a great service and has a free hacker plan. + +Note: Laravel Scout is on the demo site not active. + +### Development + +* Run `npm install` in your `/client` folder. +* Make sure you have installed `webpack` globally. +* Run `npm run dev` or `npm run build`. + +### Misc + +* Give `backend/storage` and `public/assets` recursive write access. + +### Todo + +* Settings + * Change username / password + * Export and import + * Sync scout driver +* Ajax request for settings +* Better responsive diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..d16135d --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,18 @@ +TMDB_API_KEY= +ALTERNATIVE_LANGUAGE= + +CLIENT_URI=/ +LOADING_ITEMS=30 + +SCOUT_DRIVER= +ALGOLIA_APP_ID= +ALGOLIA_SECRET= + +DB_CONNECTION=mysql +DB_DATABASE= +DB_USERNAME= +DB_PASSWORD= + +APP_ENV=local +APP_KEY= +APP_DEBUG=true \ No newline at end of file diff --git a/backend/app/Console/Commands/DB.php b/backend/app/Console/Commands/DB.php new file mode 100644 index 0000000..d8608ca --- /dev/null +++ b/backend/app/Console/Commands/DB.php @@ -0,0 +1,49 @@ +createMigrations(); + } catch(\Exception $e) { + $this->error('Can not connect to the database. Error: ' . $e->getMessage()); + $this->error('Make sure your database credentials in .env are correct'); + + return; + } + + $this->createUser(); + } + + private function createMigrations() + { + $this->info('TRYING TO MIGRATE DATABASE'); + $this->call('migrate', ['--force' => true]); + $this->info('MIGRATION COMPLETED'); + } + + private function createUser() + { + $username = $this->ask('Enter your admin username'); + $password = $this->ask('Enter your admin password'); + + $user = new User(); + $user->username = $username; + $user->password = bcrypt($password); + $user->save(); + } + } diff --git a/backend/app/Console/Commands/Init.php b/backend/app/Console/Commands/Init.php new file mode 100644 index 0000000..d380422 --- /dev/null +++ b/backend/app/Console/Commands/Init.php @@ -0,0 +1,64 @@ + 'Name', + 'DB_USERNAME' => 'Username', + 'DB_PASSWORD' => 'Password', + ]; + + public function __construct() + { + parent::__construct(); + } + + public function handle() + { + $this->createENVFile(); + $this->fillDatabaseCredentials(); + $this->setAppKey(); + } + + private function createENVFile() + { + if( ! file_exists('.env')) { + $this->info('CREATING .ENV FILE'); + copy('.env.example', '.env'); + } + } + + private function fillDatabaseCredentials() + { + foreach($this->requests as $type => $text) { + if( ! env($type)) { + $value = $this->ask('Enter your Database ' . $text); + $this->changeENV($type, $value); + } + } + } + + private function setAppKey() + { + if( ! env('APP_KEY')) { + $this->info('GENERATING APP KEY'); + $this->callSilent('key:generate'); + } + } + + private function changeENV($type, $value) + { + file_put_contents('.env', str_replace( + $type . '=', + $type . '=' . $value, + file_get_contents('.env') + )); + } + } diff --git a/backend/app/Console/Commands/Sync.php b/backend/app/Console/Commands/Sync.php new file mode 100644 index 0000000..f2f3532 --- /dev/null +++ b/backend/app/Console/Commands/Sync.php @@ -0,0 +1,32 @@ +info('TRYING TO SYNC YOUR MOVIES TO ' . strtoupper($scoutDriver)); + $this->call('scout:import', ['model' => 'App\\Item']); + $this->info('SYNCHRONIZATION COMPLETED'); + } catch(\Exception $e) { + $this->error('Can not connect to ' . $scoutDriver . '. Error: ' . $e->getMessage()); + $this->error('Make sure your ' . $scoutDriver . ' credentials in .env are correct'); + + return; + } + } + } diff --git a/backend/app/Console/Kernel.php b/backend/app/Console/Kernel.php new file mode 100644 index 0000000..f73af16 --- /dev/null +++ b/backend/app/Console/Kernel.php @@ -0,0 +1,42 @@ +command('inspire') + // ->hourly(); + } + + /** + * Register the Closure based commands for the application. + * + * @return void + */ + protected function commands() + { + require base_path('routes/console.php'); + } +} diff --git a/backend/app/Exceptions/Handler.php b/backend/app/Exceptions/Handler.php new file mode 100644 index 0000000..21c9784 --- /dev/null +++ b/backend/app/Exceptions/Handler.php @@ -0,0 +1,65 @@ +expectsJson()) { + return response()->json(['error' => 'Unauthenticated.'], 401); + } + + return redirect()->guest('login'); + } +} diff --git a/backend/app/Http/Controllers/Controller.php b/backend/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..03e02a2 --- /dev/null +++ b/backend/app/Http/Controllers/Controller.php @@ -0,0 +1,13 @@ +loadingItems = config('app.LOADING_ITEMS'); + $this->item = $item; + } + + /** + * Return all items for home with pagination. + * + * @param $orderBy + * @return mixed + */ + public function items($orderBy) + { + $orderType = $orderBy == 'rating' ? 'asc' : 'desc'; + + return $this->item->orderBy($orderBy, $orderType)->simplePaginate($this->loadingItems); + } + + /** + * Search for items by 'title' in database or with Laravel Scout. + * + * @return mixed + */ + public function search() + { + $title = Input::get('q'); + + if(config('scout.driver')) { + return $this->item->search($title)->get(); + } + + // We don't have an smart search driver and return an simple 'like' query. + return $this->item->where('title', 'LIKE', '%' . $title . '%') + ->orWhere('alternative_title', 'LIKE', '%' . $title . '%') + ->get(); + } + + /** + * Update rating for an movie. + * + * @param $itemID + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response + */ + public function changeRating($itemID) + { + $item = $this->item->find($itemID); + + if( ! $item) { + return response('Not Found', 404); + } + + $item->update([ + 'rating' => Input::get('rating') + ]); + } + + /** + * Add a new movie to database and create the poster image file. + * + * @param TMDB $tmdb + * @return Item + */ + public function add(TMDB $tmdb) + { + $data = Input::get('item'); + + $this->createPosterFile($data['poster']); + + return $this->createItem($data, $tmdb); + } + + /** + * Delete movie in database and delete the poster image file. + * + * @param $itemID + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response + */ + public function remove($itemID) + { + $item = $this->item->find($itemID); + + if( ! $item) { + return response('Not Found', 404); + } + + $this->removePosterFile($item->poster); + + $item->delete(); + } + + /** + * Create the new movie. + * + * @param $data + * @param $tmdb + * @return Item + */ + private function createItem($data, $tmdb) + { + return $this->item->create([ + 'tmdb_id' => $data['tmdb_id'], + 'title' => $data['title'], + 'alternative_title' => $tmdb->alternativeMovieTitle($data["tmdb_id"]), + 'poster' => $data['poster'], + 'rating' => 1, + 'released' => $data['released'], + 'created_at' => time(), + ]); + } + + /** + * Create the poster image file. + * + * @param $poster + */ + private function createPosterFile($poster) + { + if($poster) { + Storage::put($poster, file_get_contents('http://image.tmdb.org/t/p/w185' . $poster)); + } + } + + /** + * Delete the poster image file. + * + * @param $poster + */ + private function removePosterFile($poster) + { + Storage::delete($poster); + } + } \ No newline at end of file diff --git a/backend/app/Http/Controllers/TMDBController.php b/backend/app/Http/Controllers/TMDBController.php new file mode 100644 index 0000000..1aab16d --- /dev/null +++ b/backend/app/Http/Controllers/TMDBController.php @@ -0,0 +1,21 @@ +tmdb = $tmdb; + } + + public function search() + { + return $this->tmdb->search(Input::get('q')); + } + } \ No newline at end of file diff --git a/backend/app/Http/Controllers/UserController.php b/backend/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..4d0731a --- /dev/null +++ b/backend/app/Http/Controllers/UserController.php @@ -0,0 +1,50 @@ +auth = $auth; + } + + /** + * Login user and return correct response. + * + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response + */ + public function login() + { + $username = Input::get('username'); + $password = Input::get('password'); + + if($this->auth->attempt(['username' => $username, 'password' => $password], true)) { + return response('Success', 200); + } + + return response('Unauthorized', 401); + } + + /** + * Logout user and redirect to home. + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function logout() + { + $this->auth->logout(); + + return redirect('/'); + } + } \ No newline at end of file diff --git a/backend/app/Http/Kernel.php b/backend/app/Http/Kernel.php new file mode 100644 index 0000000..bcabec4 --- /dev/null +++ b/backend/app/Http/Kernel.php @@ -0,0 +1,56 @@ + [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\VerifyCsrfToken::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + + 'api' => [ + 'throttle:60,1', + 'bindings', + ], + ]; + + /** + * The application's route middleware. + * + * These middleware may be assigned to groups or used individually. + * + * @var array + */ + protected $routeMiddleware = [ + 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, + 'can' => \Illuminate\Auth\Middleware\Authorize::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + ]; +} diff --git a/backend/app/Http/Middleware/EncryptCookies.php b/backend/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 0000000..3aa15f8 --- /dev/null +++ b/backend/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ +check()) { + return redirect('/home'); + } + + return $next($request); + } +} diff --git a/backend/app/Http/Middleware/VerifyCsrfToken.php b/backend/app/Http/Middleware/VerifyCsrfToken.php new file mode 100644 index 0000000..a2c3541 --- /dev/null +++ b/backend/app/Http/Middleware/VerifyCsrfToken.php @@ -0,0 +1,17 @@ + 'App\Policies\ModelPolicy', + ]; + + /** + * Register any authentication / authorization services. + * + * @return void + */ + public function boot() + { + $this->registerPolicies(); + + // + } +} diff --git a/backend/app/Providers/BroadcastServiceProvider.php b/backend/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 0000000..1dcf8d2 --- /dev/null +++ b/backend/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,26 @@ +id === (int) $userId; + }); + } +} diff --git a/backend/app/Providers/EventServiceProvider.php b/backend/app/Providers/EventServiceProvider.php new file mode 100644 index 0000000..a182657 --- /dev/null +++ b/backend/app/Providers/EventServiceProvider.php @@ -0,0 +1,32 @@ + [ + 'App\Listeners\EventListener', + ], + ]; + + /** + * Register any events for your application. + * + * @return void + */ + public function boot() + { + parent::boot(); + + // + } +} diff --git a/backend/app/Providers/RouteServiceProvider.php b/backend/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..87ffb05 --- /dev/null +++ b/backend/app/Providers/RouteServiceProvider.php @@ -0,0 +1,79 @@ +mapApiRoutes(); + + $this->mapWebRoutes(); + + // + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + * + * @return void + */ + protected function mapWebRoutes() + { + Route::group([ + 'middleware' => 'web', + 'namespace' => $this->namespace, + ], function ($router) { + require base_path('routes/web.php'); + }); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + * + * @return void + */ + protected function mapApiRoutes() + { + Route::group([ + 'middleware' => 'api', + 'namespace' => $this->namespace, + 'prefix' => 'api', + ], function ($router) { + require base_path('routes/api.php'); + }); + } +} diff --git a/backend/app/Services/TMDB.php b/backend/app/Services/TMDB.php new file mode 100644 index 0000000..08da2ab --- /dev/null +++ b/backend/app/Services/TMDB.php @@ -0,0 +1,70 @@ +apiKey = config('app.TMDB_API_KEY'); + $this->client = new Client(['base_uri' => 'http://api.themoviedb.org/']); + } + + /** + * Search TMDB for an movie by 'title'. + * + * @param $title + * @return array + */ + public function search($title) + { + $items = []; + + $response = $this->client->get('/3/search/movie', ['query' => ['api_key' => $this->apiKey, 'query' => $title]]); + $response = json_decode($response->getBody()); + + foreach($response->results as $result) { + $dtime = DateTime::createFromFormat('Y-m-d', ($result->release_date ?: '1970-12-1')); + $items[] = [ + 'tmdb_id' => $result->id, + 'title' => $result->title, + 'poster' => $result->poster_path, + 'released' => $dtime->getTimestamp(), + ]; + } + + return $items; + } + + /** + * Make a new request to TMDB to get the 'alternative language' movie title. + * + * @param $tmdb_id + * @return null|string + */ + public function alternativeMovieTitle($tmdb_id) + { + $alternativeLanguage = config('app.ALTERNATIVE_LANGUAGE'); + + $response = $this->client->get('/3/movie/' . $tmdb_id . '/alternative_titles', ['query' => ['api_key' => $this->apiKey]]); + $titles = collect(json_decode($response->getBody())->titles); + + $title = $titles->where('iso_3166_1', $alternativeLanguage); + + if($title->isEmpty()) { + return null; + } + + // '3D' is often used in the title. We don't need them. + return trim(str_replace('3D', '', $title->first()->title)); + } + } \ No newline at end of file diff --git a/backend/app/User.php b/backend/app/User.php new file mode 100644 index 0000000..7736f39 --- /dev/null +++ b/backend/app/User.php @@ -0,0 +1,16 @@ +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running. We will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/backend/bootstrap/app.php b/backend/bootstrap/app.php new file mode 100644 index 0000000..f2801ad --- /dev/null +++ b/backend/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + App\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + App\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + App\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/backend/bootstrap/autoload.php b/backend/bootstrap/autoload.php new file mode 100644 index 0000000..3830137 --- /dev/null +++ b/backend/bootstrap/autoload.php @@ -0,0 +1,34 @@ +=5.6.4", + "laravel/framework": "5.3.*", + "laravel/scout": "^1.1", + "guzzlehttp/guzzle": "^6.2", + "algolia/algoliasearch-client-php": "^1.10" + }, + "require-dev": { + "fzaninotto/faker": "~1.4", + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "~5.0", + "symfony/css-selector": "3.1.*", + "symfony/dom-crawler": "3.1.*" + }, + "autoload": { + "classmap": [ + "database" + ], + "psr-4": { + "App\\": "app/" + } + }, + "autoload-dev": { + "classmap": [ + "tests/TestCase.php" + ] + }, + "scripts": { + "post-root-package-install": [ + "php -r \"file_exists('.env') || copy('.env.example', '.env');\"" + ], + "post-create-project-cmd": [ + "php artisan key:generate" + ], + "post-install-cmd": [ + "Illuminate\\Foundation\\ComposerScripts::postInstall", + "php artisan optimize" + ], + "post-update-cmd": [ + "Illuminate\\Foundation\\ComposerScripts::postUpdate", + "php artisan optimize" + ] + }, + "config": { + "preferred-install": "dist" + } +} diff --git a/backend/composer.lock b/backend/composer.lock new file mode 100644 index 0000000..a544466 --- /dev/null +++ b/backend/composer.lock @@ -0,0 +1,3786 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "291a5cc92490ee31ada5756c81f904c1", + "content-hash": "d6ea3739805a8b4a7a24bc88f6a979d4", + "packages": [ + { + "name": "algolia/algoliasearch-client-php", + "version": "1.10.3", + "source": { + "type": "git", + "url": "https://github.com/algolia/algoliasearch-client-php.git", + "reference": "6d3a299bc388efeb14dd52cda7bb420d472b876d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/algolia/algoliasearch-client-php/zipball/6d3a299bc388efeb14dd52cda7bb420d472b876d", + "reference": "6d3a299bc388efeb14dd52cda7bb420d472b876d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0", + "satooshi/php-coveralls": "0.6.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "AlgoliaSearch": "src/", + "AlgoliaSearch\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Algolia Team", + "email": "contact@algolia.com" + }, + { + "name": "Ryan T. Catlin", + "email": "ryan.catlin@gmail.com" + }, + { + "name": "Jonathan H. Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Algolia Search API Client for PHP", + "homepage": "https://github.com/algolia/algoliasearch-client-php", + "time": "2016-10-03 16:23:46" + }, + { + "name": "classpreloader/classpreloader", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/ClassPreloader/ClassPreloader.git", + "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", + "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^1.0|^2.0", + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "ClassPreloader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com" + } + ], + "description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case", + "keywords": [ + "autoload", + "class", + "preload" + ], + "time": "2015-11-09 22:51:51" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/265b8593498b997dc2d31e75b89f053b5cc9621a", + "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "@stable" + }, + "type": "project", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "time": "2014-10-24 07:27:01" + }, + { + "name": "doctrine/inflector", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Inflector\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2015-11-06 14:35:42" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-07-15 17:22:37" + }, + { + "name": "guzzlehttp/promises", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-06-24 23:00:38" + }, + { + "name": "jakub-onderka/php-console-color", + "version": "0.1", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ], + "time": "2014-04-08 15:00:19" + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "acci@acci.cz", + "homepage": "http://www.acci.cz/" + } + ], + "time": "2015-04-20 18:58:01" + }, + { + "name": "jeremeamia/SuperClosure", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/jeremeamia/super_closure.git", + "reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/29a88be2a4846d27c1613aed0c9071dfad7b5938", + "reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^1.2|^2.0", + "php": ">=5.4", + "symfony/polyfill-php56": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "SuperClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia", + "role": "Developer" + } + ], + "description": "Serialize Closure objects, including their context and binding", + "homepage": "https://github.com/jeremeamia/super_closure", + "keywords": [ + "closure", + "function", + "lambda", + "parser", + "serializable", + "serialize", + "tokenizer" + ], + "time": "2015-12-05 17:17:57" + }, + { + "name": "laravel/framework", + "version": "v5.3.16", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "9932861dee0fef30138f9839102fb00ddd6ddce1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/9932861dee0fef30138f9839102fb00ddd6ddce1", + "reference": "9932861dee0fef30138f9839102fb00ddd6ddce1", + "shasum": "" + }, + "require": { + "classpreloader/classpreloader": "~3.0", + "doctrine/inflector": "~1.0", + "ext-mbstring": "*", + "ext-openssl": "*", + "jeremeamia/superclosure": "~2.2", + "league/flysystem": "~1.0", + "monolog/monolog": "~1.11", + "mtdowling/cron-expression": "~1.0", + "nesbot/carbon": "~1.20", + "paragonie/random_compat": "~1.4|~2.0", + "php": ">=5.6.4", + "psy/psysh": "0.7.*", + "ramsey/uuid": "~3.0", + "swiftmailer/swiftmailer": "~5.1", + "symfony/console": "3.1.*", + "symfony/debug": "3.1.*", + "symfony/finder": "3.1.*", + "symfony/http-foundation": "3.1.*", + "symfony/http-kernel": "3.1.*", + "symfony/process": "3.1.*", + "symfony/routing": "3.1.*", + "symfony/translation": "3.1.*", + "symfony/var-dumper": "3.1.*", + "vlucas/phpdotenv": "~2.2" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/exception": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "tightenco/collect": "self.version" + }, + "require-dev": { + "aws/aws-sdk-php": "~3.0", + "mockery/mockery": "~0.9.4", + "pda/pheanstalk": "~3.0", + "phpunit/phpunit": "~5.4", + "predis/predis": "~1.0", + "symfony/css-selector": "3.1.*", + "symfony/dom-crawler": "3.1.*" + }, + "suggest": { + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", + "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~5.3|~6.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", + "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", + "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).", + "symfony/css-selector": "Required to use some of the crawler integration testing tools (3.1.*).", + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (3.1.*).", + "symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "time": "2016-10-04 16:05:47" + }, + { + "name": "laravel/scout", + "version": "v1.1.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/scout.git", + "reference": "e8209540a39ab19c3e5849ab7b7bf57b4a1454a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/scout/zipball/e8209540a39ab19c3e5849ab7b7bf57b4a1454a6", + "reference": "e8209540a39ab19c3e5849ab7b7bf57b4a1454a6", + "shasum": "" + }, + "require": { + "illuminate/bus": "~5.3", + "illuminate/contracts": "~5.3", + "illuminate/database": "~5.3", + "illuminate/pagination": "~5.3", + "illuminate/queue": "~5.3", + "illuminate/support": "~5.3", + "php": ">=5.6.4" + }, + "require-dev": { + "algolia/algoliasearch-client-php": "^1.10", + "elasticsearch/elasticsearch": "^2.2", + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~5.0" + }, + "suggest": { + "algolia/algoliasearch-client-php": "Required to use the Algolia engine (^1.10).", + "elasticsearch/elasticsearch": "Required to use the Elasticsearch engine (^2.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Scout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Scout provides a driver based solution to searching your Eloquent models.", + "keywords": [ + "algolia", + "elasticsearch", + "laravel", + "search" + ], + "time": "2016-09-27 13:41:14" + }, + { + "name": "league/flysystem", + "version": "1.0.27", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "conflict": { + "league/flysystem-sftp": "<1.0.6" + }, + "require-dev": { + "ext-fileinfo": "*", + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^2.2", + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-copy": "Allows you to use Copy.com storage", + "league/flysystem-dropbox": "Allows you to use Dropbox storage", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "time": "2016-08-10 08:55:11" + }, + { + "name": "monolog/monolog", + "version": "1.21.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "~5.3" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "time": "2016-07-29 03:23:52" + }, + { + "name": "mtdowling/cron-expression", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/mtdowling/cron-expression.git", + "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", + "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Cron": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "time": "2016-01-26 21:23:30" + }, + { + "name": "nesbot/carbon", + "version": "1.21.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7b08ec6f75791e130012f206e3f7b0e76e18e3d7", + "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/translation": "~2.6|~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2015-11-04 20:07:17" + }, + { + "name": "nikic/php-parser", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4dd659edadffdc2143e4753df655d866dbfeedf0", + "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2016-09-16 12:04:44" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2016-04-03 06:00:07" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06 14:39:51" + }, + { + "name": "psr/log", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "5277094ed527a1c4477177d102fe4c53551953e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0", + "reference": "5277094ed527a1c4477177d102fe4c53551953e0", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-09-19 16:02:08" + }, + { + "name": "psy/psysh", + "version": "v0.7.2", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e64e10b20f8d229cac76399e1f3edddb57a0f280", + "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280", + "shasum": "" + }, + "require": { + "dnoegel/php-xdg-base-dir": "0.1", + "jakub-onderka/php-console-highlighter": "0.3.*", + "nikic/php-parser": "^1.2.1|~2.0", + "php": ">=5.3.9", + "symfony/console": "~2.3.10|^2.4.2|~3.0", + "symfony/var-dumper": "~2.7|~3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "~1.5", + "phpunit/phpunit": "~3.7|~4.0|~5.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/finder": "~2.1|~3.0" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.8.x-dev" + } + }, + "autoload": { + "files": [ + "src/Psy/functions.php" + ], + "psr-4": { + "Psy\\": "src/Psy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "time": "2016-03-09 05:03:14" + }, + { + "name": "ramsey/uuid", + "version": "3.5.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "a07797b986671b0dc823885a81d5e3516b931599" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/a07797b986671b0dc823885a81d5e3516b931599", + "reference": "a07797b986671b0dc823885a81d5e3516b931599", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "^1.0|^2.0", + "php": ">=5.4" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "apigen/apigen": "^4.1", + "codeception/aspect-mock": "1.0.0", + "goaop/framework": "1.0.0-alpha.2", + "ircmaxell/random-lib": "^1.1", + "jakub-onderka/php-parallel-lint": "^0.9.0", + "mockery/mockery": "^0.9.4", + "moontoast/math": "^1.1", + "phpunit/phpunit": "^4.7|>=5.0 <5.4", + "satooshi/php-coveralls": "^0.6.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2016-10-02 15:51:17" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", + "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "mockery/mockery": "~0.9.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.4-dev" + } + }, + "autoload": { + "files": [ + "lib/swift_required.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Corbyn" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Swiftmailer, free feature-rich PHP mailer", + "homepage": "http://swiftmailer.org", + "keywords": [ + "email", + "mail", + "mailer" + ], + "time": "2016-07-08 11:51:25" + }, + { + "name": "symfony/console", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/6cb0872fb57b38b3b09ff213c21ed693956b9eb0", + "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2016-09-28 00:11:12" + }, + { + "name": "symfony/debug", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/e2b3f74a67fc928adc3c1b9027f73e1bc01190a8", + "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2016-09-06 11:02:40" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5", + "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2016-07-19 10:45:57" + }, + { + "name": "symfony/finder", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/205b5ffbb518a98ba2ae60a52656c4a31ab00c6f", + "reference": "205b5ffbb518a98ba2ae60a52656c4a31ab00c6f", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2016-09-28 00:11:12" + }, + { + "name": "symfony/http-foundation", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5114f1becca9f29e3af94374f1689c83c1aa3d97", + "reference": "5114f1becca9f29e3af94374f1689c83c1aa3d97", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "symfony/expression-language": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2016-09-21 20:55:10" + }, + { + "name": "symfony/http-kernel", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/dc339d6eebadfa6e39c52868b4d4a715eff13c69", + "reference": "dc339d6eebadfa6e39c52868b4d4a715eff13c69", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0", + "symfony/debug": "~2.8|~3.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2" + }, + "conflict": { + "symfony/config": "<2.8" + }, + "require-dev": { + "symfony/browser-kit": "~2.8|~3.0", + "symfony/class-loader": "~2.8|~3.0", + "symfony/config": "~2.8|~3.0", + "symfony/console": "~2.8|~3.0", + "symfony/css-selector": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/dom-crawler": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/finder": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0", + "symfony/routing": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0", + "symfony/templating": "~2.8|~3.0", + "symfony/translation": "~2.8|~3.0", + "symfony/var-dumper": "~2.8|~3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2016-10-03 19:01:06" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "dff51f72b0706335131b00a7f49606168c582594" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-05-18 14:26:46" + }, + { + "name": "symfony/polyfill-php56", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/3edf57a8fbf9a927533344cef65ad7e1cf31030a", + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php56\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2016-05-18 14:26:46" + }, + { + "name": "symfony/polyfill-util", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ef830ce3d218e622b221d6bfad42c751d974bf99", + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "time": "2016-05-18 14:26:46" + }, + { + "name": "symfony/process", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "66de154ae86b1a07001da9fbffd620206e4faf94" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/66de154ae86b1a07001da9fbffd620206e4faf94", + "reference": "66de154ae86b1a07001da9fbffd620206e4faf94", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2016-09-29 14:13:09" + }, + { + "name": "symfony/routing", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8edf62498a1a4c57ba317664a4b698339c10cdf6", + "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "conflict": { + "symfony/config": "<2.8" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/common": "~2.2", + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/http-foundation": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/dependency-injection": "For loading routes from a service", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2016-08-16 14:58:24" + }, + { + "name": "symfony/translation", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "93013a18d272e59dab8e67f583155b78c68947eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/93013a18d272e59dab8e67f583155b78c68947eb", + "reference": "93013a18d272e59dab8e67f583155b78c68947eb", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.8" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/intl": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2016-09-06 11:02:40" + }, + { + "name": "symfony/var-dumper", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/70bfe927b86ba9999aeebd829715b0bb2cd39a10", + "reference": "70bfe927b86ba9999aeebd829715b0bb2cd39a10", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "twig/twig": "~1.20|~2.0" + }, + "suggest": { + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2016-09-29 14:13:09" + }, + { + "name": "vlucas/phpdotenv", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause-Attribution" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2016-09-01 10:05:43" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "fzaninotto/faker", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/fzaninotto/Faker.git", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "ext-intl": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "time": "2016-04-29 12:21:54" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "satooshi/php-coveralls": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2015-05-11 14:41:42" + }, + { + "name": "mockery/mockery", + "version": "0.9.5", + "source": { + "type": "git", + "url": "https://github.com/padraic/mockery.git", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2016-05-22 21:52:33" + }, + { + "name": "myclabs/deep-copy", + "version": "1.5.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2016-09-16 13:37:59" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-06-07 08:13:47" + }, + { + "name": "phpunit/php-code-coverage", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "~1.0|~2.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.4.0", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2016-07-26 14:39:29" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2016-05-12 18:03:57" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2015-09-15 10:49:45" + }, + { + "name": "phpunit/phpunit", + "version": "5.5.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "146e0fe0bb7f44d1cefade0c93e86fe0b206dd79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/146e0fe0bb7f44d1cefade0c93e86fe0b206dd79", + "reference": "146e0fe0bb7f44d1cefade0c93e86fe0b206dd79", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "^4.0.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3 || ^2.0", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/object-enumerator": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-tidy": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.5.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2016-10-03 07:48:45" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "03500345483e1e17b52e2e4d34a89c9408ab2902" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/03500345483e1e17b52e2e4d34a89c9408ab2902", + "reference": "03500345483e1e17b52e2e4d34a89c9408ab2902", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2016-10-04 11:03:26" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" + }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-08-18 05:49:44" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-06-17 09:04:28" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-01-28 13:25:10" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", + "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-11-11 19:50:13" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, + { + "name": "sebastian/version", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-02-04 12:56:52" + }, + { + "name": "symfony/css-selector", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "ca809c64072e0fe61c1c7fb3c76cdc32265042ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ca809c64072e0fe61c1c7fb3c76cdc32265042ac", + "reference": "ca809c64072e0fe61c1c7fb3c76cdc32265042ac", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2016-09-06 11:02:40" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/bb7395e8b1db3654de82b9f35d019958276de4d7", + "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2016-08-05 08:37:39" + }, + { + "name": "symfony/yaml", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/368b9738d4033c8b93454cb0dbd45d305135a6d3", + "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-09-25 08:27:07" + }, + { + "name": "webmozart/assert", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-08-09 15:02:57" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.6.4" + }, + "platform-dev": [] +} diff --git a/backend/config/app.php b/backend/config/app.php new file mode 100644 index 0000000..0cf0a4c --- /dev/null +++ b/backend/config/app.php @@ -0,0 +1,238 @@ + env('TMDB_API_KEY'), + 'ALTERNATIVE_LANGUAGE' => env('ALTERNATIVE_LANGUAGE'), + 'LOADING_ITEMS' => env('LOADING_ITEMS'), + 'CLIENT_URI' => env('CLIENT_URI'), + + /* + |-------------------------------------------------------------------------- + | Application Name + |-------------------------------------------------------------------------- + | + | This value is the name of your application. This value is used when the + | framework needs to place the application's name in a notification or + | any other location as required by the application or its packages. + */ + + 'name' => 'Flox', + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services your application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Logging Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure the log settings for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Settings: "single", "daily", "syslog", "errorlog" + | + */ + + 'log' => env('APP_LOG', 'daily'), + + 'log_level' => env('APP_LOG_LEVEL', 'debug'), + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => [ + + /* + * Laravel Framework Service Providers... + */ + Illuminate\Auth\AuthServiceProvider::class, + Illuminate\Broadcasting\BroadcastServiceProvider::class, + Illuminate\Bus\BusServiceProvider::class, + Illuminate\Cache\CacheServiceProvider::class, + Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, + Illuminate\Cookie\CookieServiceProvider::class, + Illuminate\Database\DatabaseServiceProvider::class, + Illuminate\Encryption\EncryptionServiceProvider::class, + Illuminate\Filesystem\FilesystemServiceProvider::class, + Illuminate\Foundation\Providers\FoundationServiceProvider::class, + Illuminate\Hashing\HashServiceProvider::class, + Illuminate\Mail\MailServiceProvider::class, + Illuminate\Notifications\NotificationServiceProvider::class, + Illuminate\Pagination\PaginationServiceProvider::class, + Illuminate\Pipeline\PipelineServiceProvider::class, + Illuminate\Queue\QueueServiceProvider::class, + Illuminate\Redis\RedisServiceProvider::class, + Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, + Illuminate\Session\SessionServiceProvider::class, + Illuminate\Translation\TranslationServiceProvider::class, + Illuminate\Validation\ValidationServiceProvider::class, + Illuminate\View\ViewServiceProvider::class, + + /* + * Package Service Providers... + */ + + // + + /* + * Application Service Providers... + */ + App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, + // App\Providers\BroadcastServiceProvider::class, + App\Providers\EventServiceProvider::class, + App\Providers\RouteServiceProvider::class, + + Laravel\Scout\ScoutServiceProvider::class, + + ], + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => [ + + 'App' => Illuminate\Support\Facades\App::class, + 'Artisan' => Illuminate\Support\Facades\Artisan::class, + 'Auth' => Illuminate\Support\Facades\Auth::class, + 'Blade' => Illuminate\Support\Facades\Blade::class, + 'Bus' => Illuminate\Support\Facades\Bus::class, + 'Cache' => Illuminate\Support\Facades\Cache::class, + 'Config' => Illuminate\Support\Facades\Config::class, + 'Cookie' => Illuminate\Support\Facades\Cookie::class, + 'Crypt' => Illuminate\Support\Facades\Crypt::class, + 'DB' => Illuminate\Support\Facades\DB::class, + 'Eloquent' => Illuminate\Database\Eloquent\Model::class, + 'Event' => Illuminate\Support\Facades\Event::class, + 'File' => Illuminate\Support\Facades\File::class, + 'Gate' => Illuminate\Support\Facades\Gate::class, + 'Hash' => Illuminate\Support\Facades\Hash::class, + 'Lang' => Illuminate\Support\Facades\Lang::class, + 'Log' => Illuminate\Support\Facades\Log::class, + 'Mail' => Illuminate\Support\Facades\Mail::class, + 'Notification' => Illuminate\Support\Facades\Notification::class, + 'Password' => Illuminate\Support\Facades\Password::class, + 'Queue' => Illuminate\Support\Facades\Queue::class, + 'Redirect' => Illuminate\Support\Facades\Redirect::class, + 'Redis' => Illuminate\Support\Facades\Redis::class, + 'Request' => Illuminate\Support\Facades\Request::class, + 'Response' => Illuminate\Support\Facades\Response::class, + 'Route' => Illuminate\Support\Facades\Route::class, + 'Schema' => Illuminate\Support\Facades\Schema::class, + 'Session' => Illuminate\Support\Facades\Session::class, + 'Storage' => Illuminate\Support\Facades\Storage::class, + 'URL' => Illuminate\Support\Facades\URL::class, + 'Validator' => Illuminate\Support\Facades\Validator::class, + 'View' => Illuminate\Support\Facades\View::class, + + ], + + ]; diff --git a/backend/config/auth.php b/backend/config/auth.php new file mode 100644 index 0000000..7817501 --- /dev/null +++ b/backend/config/auth.php @@ -0,0 +1,102 @@ + [ + 'guard' => 'web', + 'passwords' => 'users', + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session", "token" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + + 'api' => [ + 'driver' => 'token', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => App\User::class, + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expire time is the number of minutes that the reset token should be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => 'password_resets', + 'expire' => 60, + ], + ], + +]; diff --git a/backend/config/broadcasting.php b/backend/config/broadcasting.php new file mode 100644 index 0000000..19a59ba --- /dev/null +++ b/backend/config/broadcasting.php @@ -0,0 +1,58 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_KEY'), + 'secret' => env('PUSHER_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + // + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/backend/config/cache.php b/backend/config/cache.php new file mode 100644 index 0000000..1d3de87 --- /dev/null +++ b/backend/config/cache.php @@ -0,0 +1,91 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing a RAM based store such as APC or Memcached, there might + | be other applications utilizing the same cache. So, we'll specify a + | value to get prefixed to all our keys so we can avoid collisions. + | + */ + + 'prefix' => 'laravel', + +]; diff --git a/backend/config/compile.php b/backend/config/compile.php new file mode 100644 index 0000000..04807ea --- /dev/null +++ b/backend/config/compile.php @@ -0,0 +1,35 @@ + [ + // + ], + + /* + |-------------------------------------------------------------------------- + | Compiled File Providers + |-------------------------------------------------------------------------- + | + | Here you may list service providers which define a "compiles" function + | that returns additional files that should be compiled, providing an + | easy way to get common files from any packages you are utilizing. + | + */ + + 'providers' => [ + // + ], + +]; diff --git a/backend/config/database.php b/backend/config/database.php new file mode 100644 index 0000000..fd22e8e --- /dev/null +++ b/backend/config/database.php @@ -0,0 +1,121 @@ + PDO::FETCH_OBJ, + + /* + |-------------------------------------------------------------------------- + | Default Database Connection Name + |-------------------------------------------------------------------------- + | + | Here you may specify which of the database connections below you wish + | to use as your default connection for all database work. Of course + | you may use many connections at once using the Database library. + | + */ + + 'default' => env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Laravel is shown below to make development simple. + | + | + | All database work in Laravel is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'collation' => 'utf8_unicode_ci', + 'prefix' => '', + 'strict' => true, + 'engine' => null, + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => 'utf8', + 'prefix' => '', + 'schema' => 'public', + 'sslmode' => 'prefer', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer set of commands than a typical key-value systems + | such as APC or Memcached. Laravel makes it easy to dig right in. + | + */ + + 'redis' => [ + + 'cluster' => false, + + 'default' => [ + 'host' => env('REDIS_HOST', 'localhost'), + 'password' => env('REDIS_PASSWORD', null), + 'port' => env('REDIS_PORT', 6379), + 'database' => 0, + ], + + ], + +]; diff --git a/backend/config/filesystems.php b/backend/config/filesystems.php new file mode 100644 index 0000000..fa2d0f6 --- /dev/null +++ b/backend/config/filesystems.php @@ -0,0 +1,67 @@ + 'local', + + /* + |-------------------------------------------------------------------------- + | Default Cloud Filesystem Disk + |-------------------------------------------------------------------------- + | + | Many applications store files both locally and in the cloud. For this + | reason, you may specify a default "cloud" driver here. This driver + | will be bound as the Cloud disk implementation in the container. + | + */ + + 'cloud' => 's3', + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been setup for each driver as an example of the required options. + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => base_path('../public/assets/poster'), + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'visibility' => 'public', + ], + + 's3' => [ + 'driver' => 's3', + 'key' => 'your-key', + 'secret' => 'your-secret', + 'region' => 'your-region', + 'bucket' => 'your-bucket', + ], + + ], + + ]; diff --git a/backend/config/mail.php b/backend/config/mail.php new file mode 100644 index 0000000..9d4c4d8 --- /dev/null +++ b/backend/config/mail.php @@ -0,0 +1,115 @@ + env('MAIL_DRIVER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | SMTP Host Address + |-------------------------------------------------------------------------- + | + | Here you may provide the host address of the SMTP server used by your + | applications. A default option is provided that is compatible with + | the Mailgun mail service which will provide reliable deliveries. + | + */ + + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + + /* + |-------------------------------------------------------------------------- + | SMTP Host Port + |-------------------------------------------------------------------------- + | + | This is the SMTP port used by your application to deliver e-mails to + | users of the application. Like the host we have set this value to + | stay compatible with the Mailgun e-mail application by default. + | + */ + + 'port' => env('MAIL_PORT', 587), + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => 'hello@example.com', + 'name' => 'Example', + ], + + /* + |-------------------------------------------------------------------------- + | E-Mail Encryption Protocol + |-------------------------------------------------------------------------- + | + | Here you may specify the encryption protocol that should be used when + | the application send e-mail messages. A sensible default using the + | transport layer security protocol should provide great security. + | + */ + + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + + /* + |-------------------------------------------------------------------------- + | SMTP Server Username + |-------------------------------------------------------------------------- + | + | If your SMTP server requires a username for authentication, you should + | set it here. This will get used to authenticate with your server on + | connection. You may also set the "password" value below this one. + | + */ + + 'username' => env('MAIL_USERNAME'), + + /* + |-------------------------------------------------------------------------- + | SMTP Server Password + |-------------------------------------------------------------------------- + | + | Here you may set the password required by your SMTP server to send out + | messages from your application. This will be given to the server on + | connection so that the application will be able to send messages. + | + */ + + 'password' => env('MAIL_PASSWORD'), + + /* + |-------------------------------------------------------------------------- + | Sendmail System Path + |-------------------------------------------------------------------------- + | + | When using the "sendmail" driver to send e-mails, we will need to know + | the path to where Sendmail lives on this server. A default path has + | been provided here, which will work well on most of your systems. + | + */ + + 'sendmail' => '/usr/sbin/sendmail -bs', + +]; diff --git a/backend/config/queue.php b/backend/config/queue.php new file mode 100644 index 0000000..549322e --- /dev/null +++ b/backend/config/queue.php @@ -0,0 +1,85 @@ + env('QUEUE_DRIVER', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Laravel. You are free to add more. + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => 'your-public-key', + 'secret' => 'your-secret-key', + 'prefix' => 'https://sqs.us-east-1.amazonaws.com/your-account-id', + 'queue' => 'your-queue-name', + 'region' => 'us-east-1', + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => 'default', + 'retry_after' => 90, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/backend/config/scout.php b/backend/config/scout.php new file mode 100644 index 0000000..6f40aac --- /dev/null +++ b/backend/config/scout.php @@ -0,0 +1,83 @@ + env('SCOUT_DRIVER'), + + /* + |-------------------------------------------------------------------------- + | Index Prefix + |-------------------------------------------------------------------------- + | + | Here you may specify a prefix that will be applied to all search index + | names used by Scout. This prefix may be useful if you have multiple + | "tenants" or applications sharing the same search infrastructure. + | + */ + + 'prefix' => env('SCOUT_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Queue Data Syncing + |-------------------------------------------------------------------------- + | + | This option allows you to control if the operations that sync your data + | with your search engines are queued. When this is set to "true" then + | all automatic data syncing will get queued for better performance. + | + */ + + 'queue' => false, + + /* + |-------------------------------------------------------------------------- + | Algolia Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure your Algolia settings. Algolia is a cloud hosted + | search engine which works great with Scout out of the box. Just plug + | in your application ID and admin API key to get started searching. + | + */ + + 'algolia' => [ + 'id' => env('ALGOLIA_APP_ID'), + 'secret' => env('ALGOLIA_SECRET'), + ], + + /* + |-------------------------------------------------------------------------- + | Elasticsearch Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure your settings for Elasticsearch, which is a + | distributed, open source search and analytics engine. Feel free + | to add as many Elasticsearch servers as required by your app. + | + */ + + 'elasticsearch' => [ + 'index' => env('ELASTICSEARCH_INDEX', 'laravel'), + + 'config' => [ + 'hosts' => [ + env('ELASTICSEARCH_HOST', 'localhost'), + ], + ], + ], + +]; diff --git a/backend/config/services.php b/backend/config/services.php new file mode 100644 index 0000000..4460f0e --- /dev/null +++ b/backend/config/services.php @@ -0,0 +1,38 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + ], + + 'ses' => [ + 'key' => env('SES_KEY'), + 'secret' => env('SES_SECRET'), + 'region' => 'us-east-1', + ], + + 'sparkpost' => [ + 'secret' => env('SPARKPOST_SECRET'), + ], + + 'stripe' => [ + 'model' => App\User::class, + 'key' => env('STRIPE_KEY'), + 'secret' => env('STRIPE_SECRET'), + ], + +]; diff --git a/backend/config/session.php b/backend/config/session.php new file mode 100644 index 0000000..e2779ad --- /dev/null +++ b/backend/config/session.php @@ -0,0 +1,179 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => 120, + + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => null, + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | When using the "apc" or "memcached" session drivers, you may specify a + | cache store that should be used for these sessions. This value must + | correspond with one of the application's configured cache stores. + | + */ + + 'store' => null, + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => 'laravel_session', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN', null), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you if it can not be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE', false), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + +]; diff --git a/backend/config/view.php b/backend/config/view.php new file mode 100644 index 0000000..ad639ed --- /dev/null +++ b/backend/config/view.php @@ -0,0 +1,33 @@ + [ + realpath(base_path('../client/resources')), + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => realpath(storage_path('framework/views')), + +]; diff --git a/backend/database/.gitignore b/backend/database/.gitignore new file mode 100644 index 0000000..9b1dffd --- /dev/null +++ b/backend/database/.gitignore @@ -0,0 +1 @@ +*.sqlite diff --git a/backend/database/factories/ModelFactory.php b/backend/database/factories/ModelFactory.php new file mode 100644 index 0000000..effb785 --- /dev/null +++ b/backend/database/factories/ModelFactory.php @@ -0,0 +1,23 @@ +define(App\User::class, function (Faker\Generator $faker) { + static $password; + + return [ + 'name' => $faker->name, + 'email' => $faker->unique()->safeEmail, + 'password' => $password ?: $password = bcrypt('secret'), + 'remember_token' => str_random(10), + ]; +});*/ diff --git a/backend/database/migrations/2016_08_01_121249_create_items_table.php b/backend/database/migrations/2016_08_01_121249_create_items_table.php new file mode 100644 index 0000000..2e05217 --- /dev/null +++ b/backend/database/migrations/2016_08_01_121249_create_items_table.php @@ -0,0 +1,36 @@ +increments('id'); + $table->integer('tmdb_id')->unique(); + $table->string('title')->index(); + $table->string('alternative_title')->index()->nullable(); + $table->string('poster'); + $table->string('rating'); + $table->integer('released'); + $table->integer('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('items'); + } +} diff --git a/backend/database/migrations/2016_08_05_132344_create_users_table.php b/backend/database/migrations/2016_08_05_132344_create_users_table.php new file mode 100644 index 0000000..da5982b --- /dev/null +++ b/backend/database/migrations/2016_08_05_132344_create_users_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->string('username')->unique(); + $table->string('password'); + $table->rememberToken(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('users'); + } +} diff --git a/backend/database/seeds/.gitkeep b/backend/database/seeds/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/backend/database/seeds/.gitkeep @@ -0,0 +1 @@ + diff --git a/backend/database/seeds/DatabaseSeeder.php b/backend/database/seeds/DatabaseSeeder.php new file mode 100644 index 0000000..e119db6 --- /dev/null +++ b/backend/database/seeds/DatabaseSeeder.php @@ -0,0 +1,16 @@ +call(UsersTableSeeder::class); + } +} diff --git a/backend/phpunit.xml b/backend/phpunit.xml new file mode 100644 index 0000000..712e0af --- /dev/null +++ b/backend/phpunit.xml @@ -0,0 +1,27 @@ + + + + + ./tests + + + + + ./app + + + + + + + + + diff --git a/backend/routes/api.php b/backend/routes/api.php new file mode 100644 index 0000000..e69de29 diff --git a/backend/routes/console.php b/backend/routes/console.php new file mode 100644 index 0000000..e69de29 diff --git a/backend/routes/web.php b/backend/routes/web.php new file mode 100644 index 0000000..beda1f0 --- /dev/null +++ b/backend/routes/web.php @@ -0,0 +1,21 @@ + 'api'], function() { + + Route::post('/login', 'UserController@login'); + Route::get('/logout', 'UserController@logout'); + + Route::get('/items/{orderBy}', 'ItemController@items'); + Route::get('/search-items', 'ItemController@search'); + + Route::group(['middleware' => 'auth'], function() { + Route::get('/search-tmdb', 'TMDBController@search'); + Route::post('/add', 'ItemController@add'); + Route::patch('/change-rating/{itemID}', 'ItemController@changeRating'); + Route::delete('/remove/{itemID}', 'ItemController@remove'); + }); + }); + + Route::get('/{uri?}', function($uri = null) { + return view('app'); + })->where('uri', '(.*)'); diff --git a/backend/server.php b/backend/server.php new file mode 100644 index 0000000..5fb6379 --- /dev/null +++ b/backend/server.php @@ -0,0 +1,21 @@ + + */ + +$uri = urldecode( + parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) +); + +// This file allows us to emulate Apache's "mod_rewrite" functionality from the +// built-in PHP web server. This provides a convenient way to test a Laravel +// application without having installed a "real" web server software here. +if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { + return false; +} + +require_once __DIR__.'/public/index.php'; diff --git a/backend/storage/app/.gitignore b/backend/storage/app/.gitignore new file mode 100644 index 0000000..8f4803c --- /dev/null +++ b/backend/storage/app/.gitignore @@ -0,0 +1,3 @@ +* +!public/ +!.gitignore diff --git a/backend/storage/app/public/.gitignore b/backend/storage/app/public/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/storage/app/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/storage/framework/.gitignore b/backend/storage/framework/.gitignore new file mode 100644 index 0000000..b02b700 --- /dev/null +++ b/backend/storage/framework/.gitignore @@ -0,0 +1,8 @@ +config.php +routes.php +schedule-* +compiled.php +services.json +events.scanned.php +routes.scanned.php +down diff --git a/backend/storage/framework/cache/.gitignore b/backend/storage/framework/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/storage/framework/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/storage/framework/sessions/.gitignore b/backend/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/storage/framework/views/.gitignore b/backend/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/storage/logs/.gitignore b/backend/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/backend/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/backend/tests/ExampleTest.php b/backend/tests/ExampleTest.php new file mode 100644 index 0000000..2f2d20f --- /dev/null +++ b/backend/tests/ExampleTest.php @@ -0,0 +1,19 @@ +visit('/') + ->see('Laravel'); + } +} diff --git a/backend/tests/TestCase.php b/backend/tests/TestCase.php new file mode 100644 index 0000000..8208edc --- /dev/null +++ b/backend/tests/TestCase.php @@ -0,0 +1,25 @@ +make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); + + return $app; + } +} diff --git a/client/.babelrc b/client/.babelrc new file mode 100644 index 0000000..f1c00ce --- /dev/null +++ b/client/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": ["es2015", "stage-2"], + "plugins": ["transform-runtime"], + "comments": false +} \ No newline at end of file diff --git a/client/app/app.js b/client/app/app.js new file mode 100644 index 0000000..aaca265 --- /dev/null +++ b/client/app/app.js @@ -0,0 +1,45 @@ +require('../resources/sass/app.scss'); + +import Vue from 'vue'; +import { mapActions, mapState } from 'vuex' + +import SiteHeader from './components/Header.vue'; +import Search from './components/Search.vue'; +import SiteFooter from './components/Footer.vue'; +import Login from './components/Login.vue'; + +import router from './routes'; +import store from './store/index'; + +const App = new Vue({ + store, + router, + + created() { + this.checkForUserColorScheme(); + }, + + computed: { + ...mapState({ + colorScheme: state => state.colorScheme + }) + }, + + components: { + SiteHeader, Search, SiteFooter, Login + }, + + methods: { + ...mapActions([ 'setColorScheme' ]), + + checkForUserColorScheme() { + if( ! localStorage.getItem('color')) { + localStorage.setItem('color', 'light'); + } + + this.setColorScheme(localStorage.getItem('color')); + } + } +}); + +App.$mount('#app'); \ No newline at end of file diff --git a/client/app/components/Content/Content.vue b/client/app/components/Content/Content.vue new file mode 100644 index 0000000..37fb736 --- /dev/null +++ b/client/app/components/Content/Content.vue @@ -0,0 +1,58 @@ + + + \ No newline at end of file diff --git a/client/app/components/Content/Item.vue b/client/app/components/Content/Item.vue new file mode 100644 index 0000000..98cdebb --- /dev/null +++ b/client/app/components/Content/Item.vue @@ -0,0 +1,109 @@ + + + \ No newline at end of file diff --git a/client/app/components/Content/SearchContent.vue b/client/app/components/Content/SearchContent.vue new file mode 100644 index 0000000..19ab80f --- /dev/null +++ b/client/app/components/Content/SearchContent.vue @@ -0,0 +1,82 @@ + + + \ No newline at end of file diff --git a/client/app/components/Content/Settings.vue b/client/app/components/Content/Settings.vue new file mode 100644 index 0000000..d001a69 --- /dev/null +++ b/client/app/components/Content/Settings.vue @@ -0,0 +1,32 @@ + + + \ No newline at end of file diff --git a/client/app/components/Footer.vue b/client/app/components/Footer.vue new file mode 100644 index 0000000..540c56f --- /dev/null +++ b/client/app/components/Footer.vue @@ -0,0 +1,41 @@ + + + \ No newline at end of file diff --git a/client/app/components/Header.vue b/client/app/components/Header.vue new file mode 100644 index 0000000..604f339 --- /dev/null +++ b/client/app/components/Header.vue @@ -0,0 +1,62 @@ + + + \ No newline at end of file diff --git a/client/app/components/Login.vue b/client/app/components/Login.vue new file mode 100644 index 0000000..033f096 --- /dev/null +++ b/client/app/components/Login.vue @@ -0,0 +1,55 @@ + + + \ No newline at end of file diff --git a/client/app/components/Search.vue b/client/app/components/Search.vue new file mode 100644 index 0000000..20f1401 --- /dev/null +++ b/client/app/components/Search.vue @@ -0,0 +1,70 @@ + + + \ No newline at end of file diff --git a/client/app/config.js b/client/app/config.js new file mode 100644 index 0000000..9dc0af6 --- /dev/null +++ b/client/app/config.js @@ -0,0 +1,18 @@ +import Vue from 'vue'; +import Resource from 'vue-resource'; + +Vue.use(Resource); + +Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content'); + +const {url, uri, auth, scoutDriver} = document.body.dataset; + +export default { + uri, + url, + auth, + scoutDriver, + poster: url + '/assets/poster', + posterTMDB: 'http://image.tmdb.org/t/p/w185', + api: url + '/api' +}; \ No newline at end of file diff --git a/client/app/helper.js b/client/app/helper.js new file mode 100644 index 0000000..a76803e --- /dev/null +++ b/client/app/helper.js @@ -0,0 +1,23 @@ +export default { + methods: { + // http://stackoverflow.com/a/24559613 + scrollToTop(scrollDuration = 300) { + let cosParameter = window.scrollY / 2; + let scrollCount = 0; + let oldTimestamp = performance.now(); + + function step(newTimestamp) { + scrollCount += Math.PI / (scrollDuration / (newTimestamp - oldTimestamp)); + + if(scrollCount >= Math.PI) window.scrollTo(0, 0); + if(window.scrollY === 0) return; + + window.scrollTo(0, Math.round(cosParameter + cosParameter * Math.cos(scrollCount))); + oldTimestamp = newTimestamp; + window.requestAnimationFrame(step); + } + + window.requestAnimationFrame(step); + } + } +} \ No newline at end of file diff --git a/client/app/routes.js b/client/app/routes.js new file mode 100644 index 0000000..44da69d --- /dev/null +++ b/client/app/routes.js @@ -0,0 +1,22 @@ +import Vue from 'vue'; +import Router from 'vue-router'; + +import config from './config'; +window.config = config; + +import Content from './components/Content/Content.vue'; +import SearchContent from './components/Content/SearchContent.vue'; +import Settings from './components/Content/Settings.vue'; + +Vue.use(Router); + +export default new Router({ + mode: 'history', + base: config.uri, + routes: [ + { path: '/', component: Content }, + { path: '/search', component: SearchContent }, + { path: '/settings', component: Settings }, + { path: '*', component: Content } + ] +}); \ No newline at end of file diff --git a/client/app/store/actions.js b/client/app/store/actions.js new file mode 100644 index 0000000..e464a13 --- /dev/null +++ b/client/app/store/actions.js @@ -0,0 +1,45 @@ +import Vue from 'vue'; +import Resource from 'vue-resource'; + +Vue.use(Resource); + +export function loadItems({commit}, filter) { + commit('SET_LOADING', true); + Vue.http.get(`${config.api}/items/${filter}`).then(value => { + const {data, next_page_url} = value.data; + + commit('SET_ITEMS', data); + commit('SET_PAGINATOR', next_page_url); + + setTimeout(() => { + commit('SET_LOADING', false); + }, 500); + }, error => { + if(error.status == 404) { + window.location.href = config.url; + } + }); +} + +export function loadMoreItems({commit}, next_page_url) { + commit('SET_CLICKED_LOADING', true); + Vue.http.get(next_page_url).then(value => { + const {data, next_page_url} = value.data; + + commit('SET_PAGINATOR', next_page_url); + + setTimeout(() => { + commit('PUSH_TO_ITEMS', data); + commit('SET_CLICKED_LOADING', false); + }, 500); + }); +} + +export function setSearchTitle({commit}, title) { + commit('SET_SEARCH_TITLE', title); +} + +export function setColorScheme({commit}, color) { + localStorage.setItem('color', color); + commit('SET_COLOR_SCHEME', color); +} \ No newline at end of file diff --git a/client/app/store/index.js b/client/app/store/index.js new file mode 100644 index 0000000..c3337ea --- /dev/null +++ b/client/app/store/index.js @@ -0,0 +1,21 @@ +import Vue from 'vue'; +import Vuex from 'vuex' + +import * as actions from './actions'; +import mutations from './mutations'; + +Vue.use(Vuex); + +export default new Vuex.Store({ + state: { + items: [], + searchTitle: '', + userFilter: '', + loading: false, + clickedMoreLoading: false, + paginator: null, + colorScheme: '' + }, + mutations, + actions +}); \ No newline at end of file diff --git a/client/app/store/mutations.js b/client/app/store/mutations.js new file mode 100644 index 0000000..4b5e623 --- /dev/null +++ b/client/app/store/mutations.js @@ -0,0 +1,35 @@ +import * as type from './types'; + +export default { + [type.SET_SEARCH_TITLE](state, title) { + state.searchTitle = title; + }, + + [type.SET_USER_FILTER](state, filter) { + state.userFilter = filter; + }, + + [type.SET_ITEMS](state, items) { + state.items = items; + }, + + [type.PUSH_TO_ITEMS](state, items) { + state.items.push(...items); + }, + + [type.SET_LOADING](state, loading) { + state.loading = loading; + }, + + [type.SET_PAGINATOR](state, data) { + state.paginator = data; + }, + + [type.SET_CLICKED_LOADING](state, loading) { + state.clickedMoreLoading = loading; + }, + + [type.SET_COLOR_SCHEME](state, color) { + state.colorScheme = color; + } +} \ No newline at end of file diff --git a/client/app/store/types.js b/client/app/store/types.js new file mode 100644 index 0000000..51d5bce --- /dev/null +++ b/client/app/store/types.js @@ -0,0 +1,8 @@ +export const SET_SEARCH_TITLE = 'SET_SEARCH_TITLE'; +export const SET_USER_FILTER = 'SET_USER_FILTER'; +export const SET_ITEMS = 'SET_ITEMS'; +export const PUSH_TO_ITEMS = 'PUSH_TO_ITEMS'; +export const SET_LOADING = 'SET_LOADING'; +export const SET_PAGINATOR = 'SET_PAGINATOR'; +export const SET_CLICKED_LOADING = 'SET_CLICKED_LOADING'; +export const SET_COLOR_SCHEME = 'SET_COLOR_SCHEME'; \ No newline at end of file diff --git a/client/gulpfile.js b/client/gulpfile.js new file mode 100644 index 0000000..442dd3f --- /dev/null +++ b/client/gulpfile.js @@ -0,0 +1,19 @@ +const elixir = require('laravel-elixir'); + +require('laravel-elixir-vue-2'); + +/* + |-------------------------------------------------------------------------- + | Elixir Asset Management + |-------------------------------------------------------------------------- + | + | Elixir provides a clean, fluent API for defining some basic Gulp tasks + | for your Laravel application. By default, we are compiling the Sass + | file for our application, as well as publishing vendor resources. + | + */ + +elixir(mix => { + mix.sass('app.scss') + .webpack('app.js'); +}); diff --git a/client/package.json b/client/package.json new file mode 100644 index 0000000..5dffcaa --- /dev/null +++ b/client/package.json @@ -0,0 +1,34 @@ +{ + "private": true, + "scripts": { + "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", + "dev": "webpack -w" + }, + "dependencies": { + "babel-runtime": "^6.11.6", + "vue": "^2.0.1", + "vue-resource": "^1.0.3", + "vue-router": "^2.0.0", + "vuex": "^2.0.0" + }, + "devDependencies": { + "autoprefixer": "^6.5.0", + "babel-core": "^6.17.0", + "babel-loader": "^6.2.5", + "babel-plugin-transform-runtime": "^6.15.0", + "babel-preset-es2015": "^6.16.0", + "babel-preset-stage-2": "^6.17.0", + "cross-env": "^3.1.1", + "css-loader": "^0.25.0", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.9.0", + "lost": "^7.1.0", + "postcss-loader": "^0.13.0", + "sass-loader": "^4.0.2", + "style-loader": "^0.13.1", + "url-loader": "^0.5.7", + "vue-html-loader": "^1.2.3", + "vue-loader": "^9.5.1", + "webpack": "^1.13.2" + } +} diff --git a/client/resources/app.blade.php b/client/resources/app.blade.php new file mode 100644 index 0000000..295b413 --- /dev/null +++ b/client/resources/app.blade.php @@ -0,0 +1,37 @@ + + + + + + + + + Flox - Collect Your Movie Watch List + + + + + + +
+ @if(Request::is('login')) + + @else + + + + + @endif +
+ + + + + + \ No newline at end of file diff --git a/client/resources/sass/_base.scss b/client/resources/sass/_base.scss new file mode 100644 index 0000000..fe8606b --- /dev/null +++ b/client/resources/sass/_base.scss @@ -0,0 +1,46 @@ +* { + box-sizing: border-box; + font-family: 'Open Sans', sans-serif; +} + +body { + overflow-y: scroll; + background: #fff; + + &.dark { + background: #1c1c1c; + } +} + +// todo: webkit placeholder opacity + +html { + -webkit-text-size-adjust: 100%; +} + +input { + -webkit-appearance: none !important; +} + +.wrap, +.wrap-content { + lost-center: 1300px 20px; +} + +.wrap-content { + @include media(1) { lost-center: 1120px 20px; } + @include media(2) { lost-center: 960px 20px; } + @include media(3) { lost-center: 800px 20px; } + @include media(4) { lost-center: 620px 20px; } + @include media(6) { lost-center: 290px 20px; } +} + +input, +a { + outline: 0 +} + +::selection { + background: rgba($main1, .99); + color: #fff; +} \ No newline at end of file diff --git a/client/resources/sass/_misc.scss b/client/resources/sass/_misc.scss new file mode 100644 index 0000000..4f58419 --- /dev/null +++ b/client/resources/sass/_misc.scss @@ -0,0 +1,153 @@ +$main1: #895bff; +$main2: #f1309a; +$dark: #484848; +$rating1: #6bb01a; +$rating2: #da9527; +$rating3: #de2020; + +@mixin transition($type, $type2: '') { + @if $type2 == '' { + transition: $type .2s ease 0s; + } + @else { + transition: $type .2s ease 0s, $type2 .2s ease 0s; + } +} + +@mixin media($point) { + @if $point == 1 { + @media (max-width: 1320px) { @content; } + } + @else if $point == 2 { + @media (max-width: 1140px) { @content; } + } + @else if $point == 3 { + @media (max-width: 860px) { @content; } + } + @else if $point == 4 { + @media (max-width: 740px) { @content; } + } + @else if $point == 5 { + @media (max-width: 620px) { @content; } + } + @else if $point == 6 { + @media (max-width: 460px) { @content; } + } + @else if $point == sticky { + @media (min-width: 901px) { @content; } + } + @else { + @media (max-width: $point) { @content; } + } +} + +.loader { + width: 29px; + height: 29px; + display: block; + margin: 0 auto; + border: 4px solid rgb(241,48,154); + animation: cssload-loader 2.3s infinite ease; + + .dark & { + opacity: .6; + } + + i { + vertical-align: top; + display: inline-block; + width: 100%; + background-color: rgb(241,48,154); + animation: cssload-loader-inner 2.3s infinite ease-in; + } +} + +.fullsize-loader { + position: absolute; + left: calc(50% - 14px); + top: calc(50% - 14px); +} + +.smallsize-loader { + border: 4px solid #fff; + width: 19px; + height: 19px; + margin: 15px auto; + + i { + background-color: #fff; + } +} + +@keyframes cssload-loader { + 0% { transform: rotate(0deg); } + 25% { transform: rotate(180deg); } + 50% { transform: rotate(180deg); } + 75% { transform: rotate(360deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes cssload-loader-inner { + 0% { height: 0; } + 25% { height: 0; } + 50% { height: 100%; } + 75% { height: 100%; } + 100% { height: 0; } +} + +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+1F00-1FFF; +} +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0370-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} diff --git a/client/resources/sass/_normalize.scss b/client/resources/sass/_normalize.scss new file mode 100644 index 0000000..18ddf7f --- /dev/null +++ b/client/resources/sass/_normalize.scss @@ -0,0 +1,419 @@ +/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ + +/** + * 1. Change the default font family in all browsers (opinionated). + * 2. Prevent adjustments of font size after orientation changes in IE and iOS. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + * 2. Add the correct display in IE. + */ + +article, +aside, +details, /* 1 */ +figcaption, +figure, +footer, +header, +main, /* 2 */ +menu, +nav, +section, +summary { /* 1 */ + display: block; +} + +/** + * Add the correct display in IE 9-. + */ + +audio, +canvas, +progress, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Add the correct display in IE 10-. + * 1. Add the correct display in IE. + */ + +template, /* 1 */ +[hidden] { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * Remove the outline on focused links when they are also active or hovered + * in all browsers (opinionated). + */ + +a:active, +a:hover { + outline-width: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the bottom border in Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change font properties to `inherit` in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +select, +textarea { + font: inherit; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Restore the font weight unset by the previous rule. + */ + +optgroup { + font-weight: bold; +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Change the border, margin, and padding in all browsers (opinionated). + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on OS X. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Correct the text style of placeholders in Chrome, Edge, and Safari. + */ + +::-webkit-input-placeholder { + color: inherit; + opacity: 0.54; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} diff --git a/client/resources/sass/_shake.scss b/client/resources/sass/_shake.scss new file mode 100644 index 0000000..95e42df --- /dev/null +++ b/client/resources/sass/_shake.scss @@ -0,0 +1,129 @@ +/* * * * * * * * * * * * * * * * * * * * *\ + CSShake :: shake-horizontal + v1.5.0 + CSS classes to move your DOM + (c) 2015 @elrumordelaluz + http://elrumordelaluz.github.io/csshake/ + Licensed under MIT +\* * * * * * * * * * * * * * * * * * * * */ +.shake-horizontal { + display: inline-block; + transform-origin: center center; } + +.shake-freeze, +.shake-constant.shake-constant--hover:hover, +.shake-trigger:hover .shake-constant.shake-constant--hover { + animation-play-state: paused; } + +.shake-freeze:hover, +.shake-trigger:hover .shake-freeze, .shake-horizontal:hover, +.shake-trigger:hover .shake-horizontal { + animation-play-state: running; } + +@keyframes shake-horizontal { + 2% { + transform: translate(-2px, 0) rotate(0); } + 4% { + transform: translate(-8px, 0) rotate(0); } + 6% { + transform: translate(7px, 0) rotate(0); } + 8% { + transform: translate(3px, 0) rotate(0); } + 10% { + transform: translate(-6px, 0) rotate(0); } + 12% { + transform: translate(0px, 0) rotate(0); } + 14% { + transform: translate(-9px, 0) rotate(0); } + 16% { + transform: translate(-2px, 0) rotate(0); } + 18% { + transform: translate(3px, 0) rotate(0); } + 20% { + transform: translate(0px, 0) rotate(0); } + 22% { + transform: translate(9px, 0) rotate(0); } + 24% { + transform: translate(-5px, 0) rotate(0); } + 26% { + transform: translate(6px, 0) rotate(0); } + 28% { + transform: translate(5px, 0) rotate(0); } + 30% { + transform: translate(4px, 0) rotate(0); } + 32% { + transform: translate(-5px, 0) rotate(0); } + 34% { + transform: translate(9px, 0) rotate(0); } + 36% { + transform: translate(1px, 0) rotate(0); } + 38% { + transform: translate(7px, 0) rotate(0); } + 40% { + transform: translate(0px, 0) rotate(0); } + 42% { + transform: translate(2px, 0) rotate(0); } + 44% { + transform: translate(-3px, 0) rotate(0); } + 46% { + transform: translate(10px, 0) rotate(0); } + 48% { + transform: translate(-3px, 0) rotate(0); } + 50% { + transform: translate(10px, 0) rotate(0); } + 52% { + transform: translate(-3px, 0) rotate(0); } + 54% { + transform: translate(-5px, 0) rotate(0); } + 56% { + transform: translate(6px, 0) rotate(0); } + 58% { + transform: translate(-4px, 0) rotate(0); } + 60% { + transform: translate(10px, 0) rotate(0); } + 62% { + transform: translate(6px, 0) rotate(0); } + 64% { + transform: translate(-3px, 0) rotate(0); } + 66% { + transform: translate(1px, 0) rotate(0); } + 68% { + transform: translate(-5px, 0) rotate(0); } + 70% { + transform: translate(3px, 0) rotate(0); } + 72% { + transform: translate(-9px, 0) rotate(0); } + 74% { + transform: translate(-3px, 0) rotate(0); } + 76% { + transform: translate(6px, 0) rotate(0); } + 78% { + transform: translate(-7px, 0) rotate(0); } + 80% { + transform: translate(-3px, 0) rotate(0); } + 82% { + transform: translate(7px, 0) rotate(0); } + 84% { + transform: translate(1px, 0) rotate(0); } + 86% { + transform: translate(1px, 0) rotate(0); } + 88% { + transform: translate(8px, 0) rotate(0); } + 90% { + transform: translate(5px, 0) rotate(0); } + 92% { + transform: translate(10px, 0) rotate(0); } + 94% { + transform: translate(-4px, 0) rotate(0); } + 96% { + transform: translate(7px, 0) rotate(0); } + 98% { + transform: translate(-4px, 0) rotate(0); } + 0%, 100% { + transform: translate(0, 0) rotate(0); } } + +.shake-horizontal:hover, +.shake-trigger:hover .shake-horizontal, +.shake-horizontal.shake-freeze, +.shake-horizontal.shake-constant { + animation: shake-horizontal 100ms ease-in-out infinite; } diff --git a/client/resources/sass/_sprite.scss b/client/resources/sass/_sprite.scss new file mode 100644 index 0000000..afc38a4 --- /dev/null +++ b/client/resources/sass/_sprite.scss @@ -0,0 +1,96 @@ +/* +SCSS variables are information about icon's compiled state, stored under its original file name + +.icon-home { + width: $icon-home-width; +} + +The large array-like variables contain all information about a single icon +$icon-home: x y offset_x offset_y width height total_width total_height image_path; + +At the bottom of this section, we provide information about the spritesheet itself +$spritesheet: width height image $spritesheet-sprites; +*/ +$search-name: 'search'; +$search-x: 0px; +$search-y: 0px; +$search-offset-x: 0px; +$search-offset-y: 0px; +$search-width: 20px; +$search-height: 20px; +$search-total-width: 20px; +$search-total-height: 20px; +$search-image: '../public/assets/img/sprite.png'; +$search: (0px, 0px, 0px, 0px, 20px, 20px, 20px, 20px, '../public/assets/img/sprite.png', 'search', ); +$spritesheet-width: 20px; +$spritesheet-height: 20px; +$spritesheet-image: '../public/assets/img/sprite.png'; +$spritesheet-sprites: ($search, ); +$spritesheet: (20px, 20px, '../public/assets/img/sprite.png', $spritesheet-sprites, ); + +/* +The provided mixins are intended to be used with the array-like variables + +.icon-home { + @include sprite-width($icon-home); +} + +.icon-email { + @include sprite($icon-email); +} + +Example usage in HTML: + +`display: block` sprite: +
+ +To change `display` (e.g. `display: inline-block;`), we suggest using a common CSS class: + +// CSS +.icon { + display: inline-block; +} + +// HTML + +*/ +@mixin sprite-width($sprite) { + width: nth($sprite, 5); +} + +@mixin sprite-height($sprite) { + height: nth($sprite, 6); +} + +@mixin sprite-position($sprite) { + $sprite-offset-x: nth($sprite, 3); + $sprite-offset-y: nth($sprite, 4); + background-position: $sprite-offset-x $sprite-offset-y; +} + +@mixin sprite-image($sprite) { + $sprite-image: nth($sprite, 9); + background-image: url(#{$sprite-image}); +} + +@mixin sprite($sprite) { + @include sprite-image($sprite); + @include sprite-position($sprite); + @include sprite-width($sprite); + @include sprite-height($sprite); +} + +/* +The `sprites` mixin generates identical output to the CSS template + but can be overridden inside of SCSS + +@include sprites($spritesheet-sprites); +*/ +@mixin sprites($sprites) { + @each $sprite in $sprites { + $sprite-name: nth($sprite, 10); + .#{$sprite-name} { + @include sprite($sprite); + } + } +} diff --git a/client/resources/sass/app.scss b/client/resources/sass/app.scss new file mode 100644 index 0000000..188fcdc --- /dev/null +++ b/client/resources/sass/app.scss @@ -0,0 +1,13 @@ +@import + +'normalize', +'misc', +'sprite', +'shake', +'base', + +'components/header', +'components/search', +'components/content', +'components/login', +'components/footer'; \ No newline at end of file diff --git a/client/resources/sass/components/_content.scss b/client/resources/sass/components/_content.scss new file mode 100644 index 0000000..bdedb60 --- /dev/null +++ b/client/resources/sass/components/_content.scss @@ -0,0 +1,262 @@ +main { + float: left; + width: 100%; + padding: 110px 0 0 0; + min-height: 100vh; + + .dark & { + background: #1c1c1c; + } +} + +.item-wrap { + margin: 0 0 60px 0; + + lost-column: 1/6; + + @include media(1) { lost-column: 1/4; } + @include media(3) { lost-column: 1/5; } + @include media(4) { lost-column: 1/4; } + @include media(5) { lost-column: 1/3; } + @include media(6) { lost-column: 1/2; } +} + +.item-image-wrap { + position: relative; + float: left; + max-height: 278px; + + @include media(3) { + width: 120px; + height: auto; + } + + @include media(6) { + width: 100px; + } + + &:hover { + .item-new { + display: block; + } + } +} + +.item-image { + box-shadow: 0 12px 15px 0 rgba(0, 0, 0, .5); + + @include media(3) { + width: 100%; + height: auto; + } +} + +.no-image { + width: 185px; + height: 270px; + background: $dark; + float: left; + box-shadow: 0 5px 10px 0 rgba(0,0,0,.5); +} + +.item-content { + float: left; + width: 100%; + margin: 20px 0 0 0; + + @include media(5) { + margin: 10px 0 0 0; + } +} + +.item-year { + float: left; + color: #888; + font-size: 14px; + + .dark & { + color: #626262; + } +} + +.item-title { + color: $dark; + clear: both; + font-size: 17px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 100%; + text-decoration: none; + float: left; + + .dark & { + color: #717171; + } + + &:hover { + color: $main2; + } + + &:active { + color: $main1; + } +} + +.item-rating { + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + transform: translate(-50%, -50%); + box-shadow: 0 0 15px 0 rgba(0,0,0,.7); + border-radius: 25px; + + .logged & { + cursor: pointer; + + &:hover { + transform: translate(-50%, -50%) scale(1.2); + } + + &:active { + transform: translate(-50%, -50%) scale(1.1); + } + + @include transition(transform, background); + } +} + +.rating-1 { + background: $rating1; + + .icon-rating { + background: url(../../../public/assets/img/rating-1.png); + } +} +.rating-2 { + background: $rating2; + + .icon-rating { + background: url(../../../public/assets/img/rating-2.png); + } +} +.rating-3 { + background: $rating3; + + .icon-rating { + background: url(../../../public/assets/img/rating-3.png); + } +} + +.icon-rating { + width: 50px; + height: 50px; + display: block; +} + +.item-new { + background: $main1; + display: none; + + @include media(3) { + display: block; + } +} + +.icon-add { + background: url(../../../public/assets/img/add.png); + width: 50px; + height: 50px; + display: block; +} + +.remove-item { + position: absolute; + bottom: 0; + right: 0; + opacity: 0; + background: $rating3; + padding: 12px; + cursor: pointer; + + .dark & { + background: darken($rating3, 10%); + } + + @include transition(opacity); + + &:hover { + opacity: 1; + } + + @include media(3) { + // opacity: 1; + } +} + +.icon-remove { + background: url(../../../public/assets/img/remove.png); + width: 17px; + height: 17px; + display: block; +} + +.fade-enter-active { + transition: opacity .5s ease; + opacity: 1; + visibility: visible; +} + +.fade-enter { + opacity: 0; + visibility: hidden; +} + +.box { + float: left; + width: 100%; + + h2 { + float: left; + width: 100%; + margin: 0 0 30px 0; + color: $main1; + } +} + +.nothing-found { + float: left; + width: 100%; + font-size: 32px; + margin: 0 0 30px 0; + color: $dark; +} + +.load-more-wrap { + float: left; + height: 100px; + position: relative; + width: 100%; +} + +.load-more { + float: left; + width: 100%; + padding: 15px; + background: #e1e1e1; + color: $dark; + text-align: center; + font-size: 15px; + cursor: pointer; + + .dark & { + background: #2f2f2f; + color: #626262; + } + + &:active { + opacity: .8; + } +} \ No newline at end of file diff --git a/client/resources/sass/components/_footer.scss b/client/resources/sass/components/_footer.scss new file mode 100644 index 0000000..1558ddf --- /dev/null +++ b/client/resources/sass/components/_footer.scss @@ -0,0 +1,61 @@ +footer { + padding: 40px 0; + width: 100%; + float: left; + background: $main2; + background: linear-gradient(to right, $main1, $main2); + + .dark & { + opacity: .9; + } +} + +.attribution { + color: #fff; + float: left; +} + +.icon-tmdb { + background: url(../../../public/assets/img/tmdb.png); + width: 139px; + height: 18px; + float: left; + margin: 3px 10px 0 0; + + &:active { + opacity: .6; + } +} + +.icon-github { + background: url(../../../public/assets/img/github.png); + width: 33px; + height: 27px; + float: right; + + @include media(3) { + float: left; + clear: both; + margin: 30px 0 0 0; + } + + &:active { + opacity: .6; + } +} + +.sub-links { + float: left; + clear: both; +} + +.login-btn { + float: left; + color: #fff; + text-decoration: none; + margin: 20px 20px 0 0; + + &:active { + opacity: .6; + } +} \ No newline at end of file diff --git a/client/resources/sass/components/_header.scss b/client/resources/sass/components/_header.scss new file mode 100644 index 0000000..65a713d --- /dev/null +++ b/client/resources/sass/components/_header.scss @@ -0,0 +1,92 @@ +header { + background: $main2; + background: linear-gradient(to right, $main1, $main2); + width: 100%; + padding: 25px 0; + + @include media(5) { + padding: 15px 0; + } + + .dark & { + opacity: .9; + } +} + +.logo { + float: left; + + @include media(5) { + width: 80px; + height: auto; + margin: 7px 0 0 0; + + img { + width: 100%; + height: auto; + } + } +} + +.sort-wrap { + float: right; + margin: 4px 0 0 0; + width: auto; + + .icon-sort-time, + .icon-sort-star { + float: left; + width: 32px; + height: 30px; + margin: 0 0 0 15px; + cursor: pointer; + opacity: .5; + + @include transition(opacity); + + &.active { + opacity: 1; + } + + &:active { + opacity: .3; + } + + &:first-child { + margin: 0; + } + } +} + +.icon-sort-time { + background: url(../../../public/assets/img/sort-time.png); +} + +.icon-sort-star { + background: url(../../../public/assets/img/sort-star.png); +} + +.icon-constrast { + float: left; + width: 34px; + height: 34px; + margin: 0 0 0 30px; + cursor: pointer; + padding: 10px; + + &:active { + opacity: .8; + } + + i { + background: darken($dark, 20%); + border-radius: 100%; + width: 100%; + height: 100%; + float: left; + + .dark & { + background: #fff; + } + } +} \ No newline at end of file diff --git a/client/resources/sass/components/_login.scss b/client/resources/sass/components/_login.scss new file mode 100644 index 0000000..10dc62f --- /dev/null +++ b/client/resources/sass/components/_login.scss @@ -0,0 +1,61 @@ +.login-wrap { + lost-center: 320px 20px; + + @include media(4) { + width: 100%; + } +} + +.top-bar { + float: left; + width: 100%; + height: 30px; + background: $main2; + background: linear-gradient(to right, $main1, $main2); +} + +.logo-login { + display: block; + margin: 30vh auto 50px auto; +} + +.login-form { + float: left; + width: 100%; + + input[type="text"], + input[type="password"] { + float: left; + width: 100%; + font-size: 15px; + margin: 0 0 5px 0; + background: #333; + padding: 12px; + color: #fff; + border: 0; + } + + input[type="submit"] { + background: $main2; + background: linear-gradient(to right, $main1, $main2); + color: #fff; + font-size: 17px; + border: 0; + text-transform: uppercase; + padding: 8px 20px; + cursor: pointer; + } +} + +.login-error { + float: left; + height: 20px; + width: 100%; + margin: 10px 0; + + span { + float: left; + color: $rating3; + font-size: 14px; + } +} \ No newline at end of file diff --git a/client/resources/sass/components/_search.scss b/client/resources/sass/components/_search.scss new file mode 100644 index 0000000..36f6b68 --- /dev/null +++ b/client/resources/sass/components/_search.scss @@ -0,0 +1,104 @@ +.search-wrap { + float: left; + width: 100%; + position: absolute; + box-shadow: 0 0 70px 0 rgba(0, 0, 0, .3); + background: #fff; + opacity: .97; + + .dark & { + background: #2f2f2f; + } + + &.sticky { + @include media(sticky) { + position: fixed; + top: 0; + left: 0; + z-index: 10; + } + } +} + +.search-form { + float: right; + width: 100%; + position: relative; + + @include transition(padding); + + .sticky & { + padding: 0 0 0 50px; + } +} + +.search-input { + float: left; + background: transparent; + width: 100%; + border: 0; + font-size: 19px; + padding: 12px 0 12px 30px; + color: $dark; + + .dark & { + color: #989898; + } +} + +.icon-search { + background: url(../../../public/assets/img/search.png); + height: 20px; + width: 20px; + position: absolute; + left: 0; + top: 15px; + + @include transition(left); + + .dark & { + background: url(../../../public/assets/img/search-dark.png); + } + + .sticky & { + left: 50px; + } +} + +.icon-algolia { + background: url(../../../public/assets/img/algolia-white.png); + height: 25px; + width: 80px; + position: absolute; + right: 0; + top: 15px; + + .dark & { + background: url(../../../public/assets/img/algolia-dark.png); + } +} + +.icon-logo-small { + background: url(../../../public/assets/img/logo-small.png); + width: 32px; + height: 25px; + opacity: 0; + top: 12px; + left: -50px; + position: absolute; + + @include transition(opacity, left); + + .sticky & { + opacity: 1; + left: 0; + + .dark & { + opacity: .9; + } + + &:active { + opacity: .6; + } + } +} \ No newline at end of file diff --git a/client/webpack.config.js b/client/webpack.config.js new file mode 100644 index 0000000..558515b --- /dev/null +++ b/client/webpack.config.js @@ -0,0 +1,70 @@ +const webpack = require('webpack'); +const path = require('path'); +const autoprefixer = require('autoprefixer'); +const lost = require('lost'); +const ExtractTextPlugin = require("extract-text-webpack-plugin"); + +module.exports = { + entry: { + app: './app/app.js', + vendor: ['vue', 'vue-resource', 'vuex'] + }, + output: { + path: path.resolve('../public/assets'), + filename: 'app.js' + }, + resolve: { + alias: { + vue: 'vue/dist/vue.js' + } + }, + module: { + loaders: [ + { + test: /\.vue$/, + loader: 'vue' + }, + { + test: /\.js$/, + loader: 'babel', + exclude: /node_modules/ + }, + { + test: /\.(png|jpg|svg)$/, + loader: 'url', + query: { + limit: 10000, + name: 'img/[name].[ext]', + emitFile: false + } + }, + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract('style', 'css!postcss!sass') + } + ] + }, + postcss() { + return [autoprefixer, lost]; + }, + plugins: [ + new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'), + new ExtractTextPlugin('app.css') + ] +}; + +if(process.env.NODE_ENV === 'production') { + module.exports.plugins = (module.exports.plugins || []).concat([ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: '"production"' + } + }), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + } + }), + new webpack.optimize.OccurenceOrderPlugin() + ]) +} \ No newline at end of file diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..903f639 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,20 @@ + + + Options -MultiViews + + + RewriteEngine On + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.*)/$ /$1 [L,R=301] + + # Handle Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + diff --git a/public/assets/app.css b/public/assets/app.css new file mode 100644 index 0000000..f707b50 --- /dev/null +++ b/public/assets/app.css @@ -0,0 +1,1555 @@ +/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ +/** + * 1. Change the default font family in all browsers (opinionated). + * 2. Prevent adjustments of font size after orientation changes in IE and iOS. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove the margin in all browsers (opinionated). + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + * 2. Add the correct display in IE. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +main, +menu, +nav, +section, +summary { + /* 1 */ + display: block; } + +/** + * Add the correct display in IE 9-. + */ +audio, +canvas, +progress, +video { + display: inline-block; } + +/** + * Add the correct display in iOS 4-7. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + vertical-align: baseline; } + +/** + * Add the correct display in IE 10-. + * 1. Add the correct display in IE. + */ +template, +[hidden] { + display: none; } + +/* Links + ========================================================================== */ +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ +a { + background-color: transparent; + /* 1 */ + -webkit-text-decoration-skip: objects; + /* 2 */ } + +/** + * Remove the outline on focused links when they are also active or hovered + * in all browsers (opinionated). + */ +a:active, +a:hover { + outline-width: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * 1. Remove the bottom border in Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; + /* 1 */ + text-decoration: underline; + /* 2 */ + text-decoration: underline dotted; + /* 2 */ } + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ +b, +strong { + font-weight: inherit; } + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; } + +/** + * Add the correct font style in Android 4.3-. + */ +dfn { + font-style: italic; } + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Add the correct background and color in IE 9-. + */ +mark { + background-color: #ff0; + color: #000; } + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sub { + bottom: -0.25em; } + +sup { + top: -0.5em; } + +/* Embedded content + ========================================================================== */ +/** + * Remove the border on images inside links in IE 10-. + */ +img { + border-style: none; } + +/** + * Hide the overflow in IE. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ } + +/** + * Add the correct margin in IE 8. + */ +figure { + margin: 1em 40px; } + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ } + +/* Forms + ========================================================================== */ +/** + * 1. Change font properties to `inherit` in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +select, +textarea { + font: inherit; + /* 1 */ + margin: 0; + /* 2 */ } + +/** + * Restore the font weight unset by the previous rule. + */ +optgroup { + font-weight: bold; } + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, +input { + /* 1 */ + overflow: visible; } + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { + /* 1 */ + text-transform: none; } + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; + /* 2 */ } + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; } + +/** + * Change the border, margin, and padding in all browsers (opinionated). + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; + /* 1 */ + color: inherit; + /* 2 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + white-space: normal; + /* 1 */ } + +/** + * Remove the default vertical scrollbar in IE. + */ +textarea { + overflow: auto; } + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ } + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on OS X. + */ +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Correct the text style of placeholders in Chrome, Edge, and Safari. + */ +::-webkit-input-placeholder { + color: inherit; + opacity: 0.54; } + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ } + +.loader { + width: 29px; + height: 29px; + display: block; + margin: 0 auto; + border: 4px solid #f1309a; + -webkit-animation: cssload-loader 2.3s infinite ease; + animation: cssload-loader 2.3s infinite ease; } + .dark .loader { + opacity: .6; } + .loader i { + vertical-align: top; + display: inline-block; + width: 100%; + background-color: #f1309a; + -webkit-animation: cssload-loader-inner 2.3s infinite ease-in; + animation: cssload-loader-inner 2.3s infinite ease-in; } + +.fullsize-loader { + position: absolute; + left: calc(50% - 14px); + top: calc(50% - 14px); } + +.smallsize-loader { + border: 4px solid #fff; + width: 19px; + height: 19px; + margin: 15px auto; } + .smallsize-loader i { + background-color: #fff; } + +@-webkit-keyframes cssload-loader { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 25% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + 75% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes cssload-loader { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 25% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + 50% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + 75% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@-webkit-keyframes cssload-loader-inner { + 0% { + height: 0; } + 25% { + height: 0; } + 50% { + height: 100%; } + 75% { + height: 100%; } + 100% { + height: 0; } } + +@keyframes cssload-loader-inner { + 0% { + height: 0; } + 25% { + height: 0; } + 50% { + height: 100%; } + 75% { + height: 100%; } + 100% { + height: 0; } } + +/* cyrillic-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; } + +/* cyrillic */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } + +/* greek-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+1F00-1FFF; } + +/* greek */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+0370-03FF; } + +/* vietnamese */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; } + +/* latin-ext */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format("woff2"); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; } + +/* latin */ +@font-face { + font-family: 'Open Sans'; + font-style: normal; + font-weight: 400; + src: local("Open Sans"), local("OpenSans"), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; } + +/* +SCSS variables are information about icon's compiled state, stored under its original file name + +.icon-home { + width: $icon-home-width; +} + +The large array-like variables contain all information about a single icon +$icon-home: x y offset_x offset_y width height total_width total_height image_path; + +At the bottom of this section, we provide information about the spritesheet itself +$spritesheet: width height image $spritesheet-sprites; +*/ +/* +The provided mixins are intended to be used with the array-like variables + +.icon-home { + @include sprite-width($icon-home); +} + +.icon-email { + @include sprite($icon-email); +} + +Example usage in HTML: + +`display: block` sprite: +
+ +To change `display` (e.g. `display: inline-block;`), we suggest using a common CSS class: + +// CSS +.icon { + display: inline-block; +} + +// HTML + +*/ +/* +The `sprites` mixin generates identical output to the CSS template + but can be overridden inside of SCSS + +@include sprites($spritesheet-sprites); +*/ +/* * * * * * * * * * * * * * * * * * * * * CSShake :: shake-horizontal + v1.5.0 + CSS classes to move your DOM + (c) 2015 @elrumordelaluz + http://elrumordelaluz.github.io/csshake/ + Licensed under MIT +\* * * * * * * * * * * * * * * * * * * * */ +.shake-horizontal { + display: inline-block; + -webkit-transform-origin: center center; + transform-origin: center center; } + +.shake-freeze, +.shake-constant.shake-constant--hover:hover, +.shake-trigger:hover .shake-constant.shake-constant--hover { + -webkit-animation-play-state: paused; + animation-play-state: paused; } + +.shake-freeze:hover, +.shake-trigger:hover .shake-freeze, .shake-horizontal:hover, +.shake-trigger:hover .shake-horizontal { + -webkit-animation-play-state: running; + animation-play-state: running; } + +@-webkit-keyframes shake-horizontal { + 2% { + -webkit-transform: translate(-2px, 0) rotate(0); + transform: translate(-2px, 0) rotate(0); } + 4% { + -webkit-transform: translate(-8px, 0) rotate(0); + transform: translate(-8px, 0) rotate(0); } + 6% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 8% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 10% { + -webkit-transform: translate(-6px, 0) rotate(0); + transform: translate(-6px, 0) rotate(0); } + 12% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 14% { + -webkit-transform: translate(-9px, 0) rotate(0); + transform: translate(-9px, 0) rotate(0); } + 16% { + -webkit-transform: translate(-2px, 0) rotate(0); + transform: translate(-2px, 0) rotate(0); } + 18% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 20% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 22% { + -webkit-transform: translate(9px, 0) rotate(0); + transform: translate(9px, 0) rotate(0); } + 24% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 26% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 28% { + -webkit-transform: translate(5px, 0) rotate(0); + transform: translate(5px, 0) rotate(0); } + 30% { + -webkit-transform: translate(4px, 0) rotate(0); + transform: translate(4px, 0) rotate(0); } + 32% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 34% { + -webkit-transform: translate(9px, 0) rotate(0); + transform: translate(9px, 0) rotate(0); } + 36% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 38% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 40% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 42% { + -webkit-transform: translate(2px, 0) rotate(0); + transform: translate(2px, 0) rotate(0); } + 44% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 46% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 48% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 50% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 52% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 54% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 56% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 58% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 60% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 62% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 64% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 66% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 68% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 70% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 72% { + -webkit-transform: translate(-9px, 0) rotate(0); + transform: translate(-9px, 0) rotate(0); } + 74% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 76% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 78% { + -webkit-transform: translate(-7px, 0) rotate(0); + transform: translate(-7px, 0) rotate(0); } + 80% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 82% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 84% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 86% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 88% { + -webkit-transform: translate(8px, 0) rotate(0); + transform: translate(8px, 0) rotate(0); } + 90% { + -webkit-transform: translate(5px, 0) rotate(0); + transform: translate(5px, 0) rotate(0); } + 92% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 94% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 96% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 98% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 0%, 100% { + -webkit-transform: translate(0, 0) rotate(0); + transform: translate(0, 0) rotate(0); } } + +@keyframes shake-horizontal { + 2% { + -webkit-transform: translate(-2px, 0) rotate(0); + transform: translate(-2px, 0) rotate(0); } + 4% { + -webkit-transform: translate(-8px, 0) rotate(0); + transform: translate(-8px, 0) rotate(0); } + 6% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 8% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 10% { + -webkit-transform: translate(-6px, 0) rotate(0); + transform: translate(-6px, 0) rotate(0); } + 12% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 14% { + -webkit-transform: translate(-9px, 0) rotate(0); + transform: translate(-9px, 0) rotate(0); } + 16% { + -webkit-transform: translate(-2px, 0) rotate(0); + transform: translate(-2px, 0) rotate(0); } + 18% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 20% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 22% { + -webkit-transform: translate(9px, 0) rotate(0); + transform: translate(9px, 0) rotate(0); } + 24% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 26% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 28% { + -webkit-transform: translate(5px, 0) rotate(0); + transform: translate(5px, 0) rotate(0); } + 30% { + -webkit-transform: translate(4px, 0) rotate(0); + transform: translate(4px, 0) rotate(0); } + 32% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 34% { + -webkit-transform: translate(9px, 0) rotate(0); + transform: translate(9px, 0) rotate(0); } + 36% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 38% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 40% { + -webkit-transform: translate(0px, 0) rotate(0); + transform: translate(0px, 0) rotate(0); } + 42% { + -webkit-transform: translate(2px, 0) rotate(0); + transform: translate(2px, 0) rotate(0); } + 44% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 46% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 48% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 50% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 52% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 54% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 56% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 58% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 60% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 62% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 64% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 66% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 68% { + -webkit-transform: translate(-5px, 0) rotate(0); + transform: translate(-5px, 0) rotate(0); } + 70% { + -webkit-transform: translate(3px, 0) rotate(0); + transform: translate(3px, 0) rotate(0); } + 72% { + -webkit-transform: translate(-9px, 0) rotate(0); + transform: translate(-9px, 0) rotate(0); } + 74% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 76% { + -webkit-transform: translate(6px, 0) rotate(0); + transform: translate(6px, 0) rotate(0); } + 78% { + -webkit-transform: translate(-7px, 0) rotate(0); + transform: translate(-7px, 0) rotate(0); } + 80% { + -webkit-transform: translate(-3px, 0) rotate(0); + transform: translate(-3px, 0) rotate(0); } + 82% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 84% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 86% { + -webkit-transform: translate(1px, 0) rotate(0); + transform: translate(1px, 0) rotate(0); } + 88% { + -webkit-transform: translate(8px, 0) rotate(0); + transform: translate(8px, 0) rotate(0); } + 90% { + -webkit-transform: translate(5px, 0) rotate(0); + transform: translate(5px, 0) rotate(0); } + 92% { + -webkit-transform: translate(10px, 0) rotate(0); + transform: translate(10px, 0) rotate(0); } + 94% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 96% { + -webkit-transform: translate(7px, 0) rotate(0); + transform: translate(7px, 0) rotate(0); } + 98% { + -webkit-transform: translate(-4px, 0) rotate(0); + transform: translate(-4px, 0) rotate(0); } + 0%, 100% { + -webkit-transform: translate(0, 0) rotate(0); + transform: translate(0, 0) rotate(0); } } + +.shake-horizontal:hover, +.shake-trigger:hover .shake-horizontal, +.shake-horizontal.shake-freeze, +.shake-horizontal.shake-constant { + -webkit-animation: shake-horizontal 100ms ease-in-out infinite; + animation: shake-horizontal 100ms ease-in-out infinite; } + +* { + box-sizing: border-box; + font-family: 'Open Sans', sans-serif; } + +body { + overflow-y: scroll; + background: #fff; } + body.dark { + background: #1c1c1c; } + +html { + -webkit-text-size-adjust: 100%; } + +input { + -webkit-appearance: none !important; } + +.wrap, +.wrap-content { + max-width: 1300px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + +.wrap:before, +.wrap-content:before { + content: ''; + display: table; } + +.wrap:after, +.wrap-content:after { + content: ''; + display: table; + clear: both; } + +@media (max-width: 1320px) { + .wrap-content { + max-width: 1120px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + .wrap-content:before { + content: ''; + display: table; } + .wrap-content:after { + content: ''; + display: table; + clear: both; } } + +@media (max-width: 1140px) { + .wrap-content { + max-width: 960px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + .wrap-content:before { + content: ''; + display: table; } + .wrap-content:after { + content: ''; + display: table; + clear: both; } } + +@media (max-width: 860px) { + .wrap-content { + max-width: 800px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + .wrap-content:before { + content: ''; + display: table; } + .wrap-content:after { + content: ''; + display: table; + clear: both; } } + +@media (max-width: 740px) { + .wrap-content { + max-width: 620px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + .wrap-content:before { + content: ''; + display: table; } + .wrap-content:after { + content: ''; + display: table; + clear: both; } } + +@media (max-width: 460px) { + .wrap-content { + max-width: 290px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + .wrap-content:before { + content: ''; + display: table; } + .wrap-content:after { + content: ''; + display: table; + clear: both; } } + +input, +a { + outline: 0; } + +::-moz-selection { + background: rgba(137, 91, 255, 0.99); + color: #fff; } + +::selection { + background: rgba(137, 91, 255, 0.99); + color: #fff; } + +header { + background: #f1309a; + background: -webkit-linear-gradient(left, #895bff, #f1309a); + background: linear-gradient(to right, #895bff, #f1309a); + width: 100%; + padding: 25px 0; } + @media (max-width: 620px) { + header { + padding: 15px 0; } } + .dark header { + opacity: .9; } + +.logo { + float: left; } + @media (max-width: 620px) { + .logo { + width: 80px; + height: auto; + margin: 7px 0 0 0; } + .logo img { + width: 100%; + height: auto; } } + +.sort-wrap { + float: right; + margin: 4px 0 0 0; + width: auto; } + .sort-wrap .icon-sort-time, + .sort-wrap .icon-sort-star { + float: left; + width: 32px; + height: 30px; + margin: 0 0 0 15px; + cursor: pointer; + opacity: .5; + -webkit-transition: opacity 0.2s ease 0s; + transition: opacity 0.2s ease 0s; } + .sort-wrap .icon-sort-time.active, + .sort-wrap .icon-sort-star.active { + opacity: 1; } + .sort-wrap .icon-sort-time:active, + .sort-wrap .icon-sort-star:active { + opacity: .3; } + .sort-wrap .icon-sort-time:first-child, + .sort-wrap .icon-sort-star:first-child { + margin: 0; } + +.icon-sort-time { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAMAAAB61OwbAAAAZlBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+Vn2moAAAAInRSTlMAzAYCx3dcMhoUs6x9wrqnkiIQC4aCdE1EPxaWjGY3Kw5puSPxJQAAAOxJREFUKM+tktt2gyAURN2IeMH7JdGkadP//8m2pgdlRc1L5mkWMwzDgeC9UHE0aD1EsdqU0xqHOn2SwxwKc1G/OYnREIW+3ln4cMnqBlXn7bfoz/VCDHadEaEb4c4RrfqB6Hm+OJamNWehIOyb2nWiDJ8NStNJmgR4huCG9D7RbhkaTqJDu2FQVI8bzpDy8LWkFfOMMoBMWtrFEVLIEODiZl7CJEfYBxlhXL15BWZmiTu37713uf4HGiZZUoEHk6V/UQX34AiG66HeQHKkJ5r+hZ6pfTk8Q9nuyu1YygfdADOq/X6QDdM9eCN+AALUB2A/c8F8AAAAAElFTkSuQmCC); } + +.icon-sort-star { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAeCAMAAAB61OwbAAAAbFBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8+T+BWAAAAJHRSTlMAzJmDTi/BtLydJIp6Uh8YEqjFo3RXSkIzDQWtr5+Of25lNykrWfzcAAABC0lEQVQoz32S6Y7DIAyE+RoSAjna3G3Su+//jiuCdiNHXeaPGcaMbGy1Q12rKA5wiOmaZUFHDbSOWWiuSl3RMQOlIhYa44NBxwwiFiNm9nE2jFJx01BaA1SBV4Cx5TC5wC0BXTKHiznpCLCeFjRFX6VH6XpMq75oKJQ6kTv1D1zOyTvkn+/6J6fwMSFLv+lpRuJjyIjpMkPqW0Z7lvq59fqGB20tFqvloQQMR/ENGKlfyORFxkWWhJUJFll2RSkTSirBe4ZwmKYQB/rdrqxtvjvo3mubu61Zp5JauN3ApusMNzVQd4fmpdSrgbtbn2yoWRIwz8CeBpIGJ2sgK/86v5QZ+82tR/mT4+/7H5CVCfc1dYw2AAAAAElFTkSuQmCC); } + +.icon-constrast { + float: left; + width: 34px; + height: 34px; + margin: 0 0 0 30px; + cursor: pointer; + padding: 10px; } + .icon-constrast:active { + opacity: .8; } + .icon-constrast i { + background: #151515; + border-radius: 100%; + width: 100%; + height: 100%; + float: left; } + .dark .icon-constrast i { + background: #fff; } + +.search-wrap { + float: left; + width: 100%; + position: absolute; + box-shadow: 0 0 70px 0 rgba(0, 0, 0, 0.3); + background: #fff; + opacity: .97; } + .dark .search-wrap { + background: #2f2f2f; } + @media (min-width: 901px) { + .search-wrap.sticky { + position: fixed; + top: 0; + left: 0; + z-index: 10; } } + +.search-form { + float: right; + width: 100%; + position: relative; + -webkit-transition: padding 0.2s ease 0s; + transition: padding 0.2s ease 0s; } + .sticky .search-form { + padding: 0 0 0 50px; } + +.search-input { + float: left; + background: transparent; + width: 100%; + border: 0; + font-size: 19px; + padding: 12px 0 12px 30px; + color: #484848; } + .dark .search-input { + color: #989898; } + +.icon-search { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAAOVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8dlA9AAAAE3RSTlMAXlUVPipREQhGJFs4Sx4NTjoyDPZNewAAAJpJREFUGNN1kEkOxDAIBN0s3h0n+f9jRyGO8GX6gFABDSKYDjmJRufg4oElmR87GiCVWQsQ0+prGLzKhJgtGxj5G0qEblW05PYV7bEVSNgUoRbrDrv1EHiHivIPntAdCi4zKRvLZCsYOBzeoPwOEPuZyyxHUH2zG2irIUUgdlUhwF+Se4OJlAm0aJgqpVw1Py/xFa5EfqOLZf4ANQ0DwYTAhJ8AAAAASUVORK5CYII=); + height: 20px; + width: 20px; + position: absolute; + left: 0; + top: 15px; + -webkit-transition: left 0.2s ease 0s; + transition: left 0.2s ease 0s; } + .dark .icon-search { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUBAMAAAB/pwA+AAAAJ1BMVEUAAACYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJipITY4AAAADXRSTlMAXhNVPSEqUTYITEYNXFFjAgAAAJpJREFUCNdjYGBg9TJeocAAAkwLBQUFRQ6AmIGCrkrZgkUgQcFFQDJYfAIDA5fUBJCAYQNQXogBrEyGgcHRAcxkF2NgKAwAMzlEGBgMIUaySaMwFyaAmSxABY0bwMzJogwMiqJgZqMlUEYYpJhVEKiOs9AUSDQKggTUBSvSnAWB7gGLCAqaKYPV8aTsdp3AZGjEAAPK0nAmkw8AZRkXEW5H1jYAAAAASUVORK5CYII=); } + .sticky .icon-search { + left: 50px; } + +.icon-algolia { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAZCAMAAACRmFk7AAABqlBMVEUAAAAdNlcdNlYdNlceNlgdNlcdNlcdNVYdNVcdN1gcOFccNlcrYIIdNlcdNVgcNlQbMVgcNVYcNVcaMk8aMVMbNFYbMlFGrtocNFcdNVcdNVYcNlcbMFAbMlMYL1MYMFoZMVFBtN4aNFJBuuMdNlcdNlYdNVgcNFYbOFcdN1dKrd4dNlgcNVVGrtodNlcdNldHrdpGrdodNVcdNVZHrtodNVgbN1YdMlYbNVgeNVgbNVZGr9tHrtsdN1pGsNxKst9AuOEbM1MdNVccNVZGr9tGrtpFsdocNVgdNlgcNlcdNFkcNVdHrdscNVQcNlVJrNsdNlceNVcaL09Gr9waMlAcNVhJrNxLq99Fr95HqtwaMFMbMVU5wOocNVccNFdIreNEr9odNlccNFYdNldGr9saM1EbMllFrtsaNFFDsuJFrdkXMEtDtOQYKkZJtOE9vuNHqt1CstwdNVccNFlGrttHrdxFsd48w+ZLq91Hrdo/tt1KsuBDstxGrtoZOlZIrNs/u9pUo+IUJTxBtN4i1+0XMkxVouNGs9gJERsT6vYdNldGrtodNlhGrdqUi/0hAAAAinRSTlMAvaT1NyA+XchsM+IC/UxFLNzRRBYMBPjpzIV4XTk1JhwKCAX7i4BXUkIO8/Lo4+DXzLGreXJvZWNgWlFBMCsmGRH579vTzcG5t7SnpqGdmJaQiomBfV9URTcoIyEhGRfw7djVv7WdfHpta1BKSTIeE+vl4+Hg2ri3tqqon56Mg3ZwZVZTPz05IwfzxWOXAAADE0lEQVQ4y63U91MaQRQH8AeYxENQQDqRIoiCvcbee40ae0nvvffev7v8z9ldTuAMMyQzfn+4nTfz9sPxdueoSLT5IJWMdckUpX9MOTpLN/UCB2KJzM7uUbEE55a9pMcEc2nwDCynxLLG+RoViQPgd0uC8a2urs3fBrAP6C/WegMcMyXBASZy2wBSdapYZ7QJ1+32mlLgyPbw8MAPI1g8t7jTfUUxRtBdGUp2NwyNEY1+HCR6OHDz5sCoAfSUlXnE4nX0J+uC/Yf6vlonT9IGmqJG0LvhB8CBljC9zOxcfOdjIr6VRwXgaaBMLLuQ4f7erNDALQd0YEHIAHoXRMdsp8kJVNHb7dFJxq6tr79mrG3/L3DMZTpf19nI9bHNY148O3ClthDUgCW3WMMStMWnM+07ohremc5Mx46DNrWzZoKrnZFx1Mv3BL9fAHqcCNhkOSRB+pR5cVEUo77FkUl22wjmch4uuVzgTzxSeIrOAjAMZCdiBaop3pb5Kostxj5vsfY4nS0GnkOFOhLUqTKIxmgerBeteXCENadl8ab5TvrRJd/D42Ak2REIdMwosApIVsqEgJ482Ac48uADNkUisTvif8cn2YNj4JdGqCjQjHwCthx4F/ieB4fZszjpiTWzESNoTcB1xrpbsyxB9wRay7Nxwm7NgQ5gg2SGJJhuZj+PwO3M85gRvMAvR/UZyoc9rHcO2fEhB3oD8EfUG6pTXmGv9C7bNbZOEozqYO50SZOgCS7bUWs5WsWFmkO5rCqBCs1a1u1S4P6lzEqMRNLvM4/35ZnZwzkwBIuad68AIwl+i44SUlexDlgQBHUnoCclqm8+NtU1ONjVxnz3shO5GvLooCOB1mB9Q18HWsRuvpsD98Cv2+iUE1hVN3/Z1Xr1hpbg1bK618ZUpgZV7ypgH6MUUCOH14Rs/NSgFX4g67U+rzinHnOVPoRar3yX7JDTm4vt7YubMb23cnWN6FDT3OoedptNc0tBLUWloo5wjE4ihyn5254zTXyBTiQ9mAiYZlo4r/h1QmBLo2V83OI379F/5A8V3evd4ZrHqwAAAABJRU5ErkJggg==); + height: 25px; + width: 80px; + position: absolute; + right: 0; + top: 15px; } + .dark .icon-algolia { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAZCAMAAACRmFk7AAABdFBMVEUAAAD///////////////////////////////////////////////////9DuuH///////////////////////////////////////////9Grtv////////////9/v5Esdz///////////////////////9Fsdr///////9HrtxLseFHq99Qr9////89vuJGrtpGrtpGrtv///9Hrtr///9Grtv///////////////////////9Ird////9Gr9v///////////9Ir93///9GrdlFr9pDsNv///////9EsNr///////////////////////////9Gr9z///////9Grdv///9JrNz///9HruJFrtv///////////////////9Gr91Gr9tJrNz///9EtN9Gr9pKqtz///9DsuJFrdn///9JtuIi1+7///9JqNj///88w+ZUo+LZ3OGstcAi1+1Pp+Ap4fX///9FruT///////9GrtpHrdlHI/5lAAAAeXRSTlMA9b03pET+IF0+bDThLQn60MhM8tyzJgzp49XLgGVYQhwWBbqMe3l4OjclFw4IBP7o2tfOt6Sjn4RwYFtUU1FQMiMdA/r37+3gysGtp5yWkIuJhoF/Yl9JSSopIRoR79+/t6qpnJdzbWtGLh/31ca4cFhVUz8WFBEPc6IlSgAAAvFJREFUOMut02dT4lAUxvEDSFaDFAWkSlUQROy99957Xftatvfn8uX33msMZGWG3Rn/L3LnvPlNkpNQmVTvFlVsos8co3+sDpdUsV3gmB8NyeQklWugZzVBWmZUUcWqYXrDjw2gicpkBzBeEcyPpFJ7DgM4BAxTmVYBLFUExxjvnQEkq5XKFHOjR1FaKoHZ6OHh2HcjWL5meOJd6HsBxuvT4dtR+2+iHztRoqmxnZ2xKQPos1h8/EjYh8MbA5ETeqrNgzBH3TEjmGj2Q6QEbPSpkGntnWW82evWErAGsIhlKxD5h0g2DtMxHZuQNoDTK4A/uZz0APd0dTDVydrPNzcv2tmHxxfgqSu51rRsgvbavPDKa1eiFFSB/jg/bYCV8vlu1p3h02Gmmy3yTUcMILURzzL/9NoanBjlxyiwXwL6PAhNy39CgJQqdIpHbZ3tzXaKTX81gFprcIljGwGfEAK4LAFtwC7R8x06goURMYww9nmEdefpSzmwEbVyJdrHviXWooMRwFIEs+0dOTFcddzlfs3NTFG1EWwIe0Ou5SUJ7gPhelEzMFgEd6HYi2CGBYnnuOPPne9kD3+BjW7IJFiFYqEiOA7UFMEH9tZBWo4OljWCE064qm1HLf0CjJ9hoe4pDxSbDtoVhElfSq6jPUNa0QLHDeA25mP6O2yEYiGRNJp0MBGCv0G/Q7phF6R1zjZJgDEN1LdLqgDNYtAKYaGNqAcfxVAP1Ko2y6BLgtm5wo186Nx1Ye5R7Eyx6GAaJrt2h+IjbNbBtPwUm6Cs3PNp0AmZIkD6NsOCqWg0FWQzB3w8UtCV9mmg3YnagcjokBcB2gCOdHAS4p954wHWxdiy6lro6ledEqSDIJMFoyRaB5RTsgItpVv207g6TMUi6tA035PaZyXZdFuC7IBNDrm93sXF3r3nbdevbxGdqGpcfoe3Veae/gHVSpWSKzyl1+jE+lP8kMNurNCrpOIsZF4KALWT9CoNBtzvnU6Tv+q/vD8U58vrvX9aEAAAAABJRU5ErkJggg==); } + +.icon-logo-small { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAZCAMAAABn0dyjAAABWVBMVEUAAACaUurfN6qsS9nEQsPCQsSSVfLjNabtMZyLWPe5Rsy6Rsy7RsyZU+rbOa3sMZ62R9C6RcywSdW8RMqfUOXVOrO2R9DTPLSZU+qnTd3MP7vbOa2ZU+rbOa3AQ8aJWfnsMp2rS9nIQL+cUefXOrCLWPe7RcrIQL+cUefXOrCkT+DQPbezSNKvStWnTd3MP7ugUOSvStXEQsKHWvvnNKHEQsKvStWcUeekT+DQPbfXOrCWVO3eN6rAQ8bIQL+rS9nIQL+gUOTTO7SLWPfqMp+ZU+rbOa2cUefXOrDIQL/MP7uHWvvuMZucUefXOrCJWfnsMp2cUeezSNLIQL+rS9mHWvu3R87TO7TTO7SrS9mXU+zdOKuPV/STVfDhNqe7RcrkNaTAQ8bEQsLnNKGKWPicUeegUOS3R87TO7TXOrDrMp+kT+CvStWzSNLQPbenTd2rS9nIQL/MP7vuPVWgAAAAWnRSTlMAEBA/CrqurpWUXQwI4eHe0ol7TSYmHRf4+Pj49/f17+/u7ufn4tDQzMy9vby4srKoo6OWlJOQjo6OjouLenNwcGlpYmJWVkhIQD8zMywsJSUX9eTh2L2qpnTJZBY7AAABI0lEQVQoz4WTVXcCMRCFAwsVoEVb6u6u1N3di7u7/P8HJpMFdsPhZF5mc+Y7NzM3s6QVGulie82yoN+5fNaS9vi6WhmuFIrpcDRWHVm9dvL1u6VUvtwAaqXM8r2qbDoZSqqB7OipSXF7l89Hgel1m8Fwpp+hgN/frW3VgwhsSOz8tIlAqEn0BhA4NBI5jEcIRPbY8SaAwBZRhBuB+C39/phHYNaBlUGrnaaBOQTMn/SCBAIHhAHhiX0d5GMEcj2EvEwiMPbAAAnGPIf8OI7A1CvZTSDQ98YE/gFYBIn3fgRA4k8GHDCuzWWhRv04oQkZMCsVNL/gJK+g6sELAN+Dagqd6zvNTcH7YLdyPnRy0iM7KXoL4WsK90G8UeKdFG+18L+oA1KFkMEV3wa7AAAAAElFTkSuQmCC); + width: 32px; + height: 25px; + opacity: 0; + top: 12px; + left: -50px; + position: absolute; + -webkit-transition: opacity 0.2s ease 0s, left 0.2s ease 0s; + transition: opacity 0.2s ease 0s, left 0.2s ease 0s; } + .sticky .icon-logo-small { + opacity: 1; + left: 0; } + .dark .sticky .icon-logo-small { + opacity: .9; } + .sticky .icon-logo-small:active { + opacity: .6; } + +main { + float: left; + width: 100%; + padding: 110px 0 0 0; + min-height: 100vh; } + .dark main { + background: #1c1c1c; } + +.item-wrap { + margin: 0 0 60px 0; + width: calc(99.9% * 1/6 - (30px - 30px * 1/6)); } + +.item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + +.item-wrap:last-child { + margin-right: 0; } + +.item-wrap:nth-child(6n) { + margin-right: 0; + float: right; } + +.item-wrap:nth-child(6n + 1) { + clear: both; } + @media (max-width: 1320px) { + .item-wrap { + width: calc(99.9% * 1/4 - (30px - 30px * 1/4)); } + .item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + .item-wrap:last-child { + margin-right: 0; } + .item-wrap:nth-child(4n) { + margin-right: 0; + float: right; } + .item-wrap:nth-child(4n + 1) { + clear: both; } } + @media (max-width: 860px) { + .item-wrap { + width: calc(99.9% * 1/5 - (30px - 30px * 1/5)); } + .item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + .item-wrap:last-child { + margin-right: 0; } + .item-wrap:nth-child(5n) { + margin-right: 0; + float: right; } + .item-wrap:nth-child(5n + 1) { + clear: both; } } + @media (max-width: 740px) { + .item-wrap { + width: calc(99.9% * 1/4 - (30px - 30px * 1/4)); } + .item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + .item-wrap:last-child { + margin-right: 0; } + .item-wrap:nth-child(4n) { + margin-right: 0; + float: right; } + .item-wrap:nth-child(4n + 1) { + clear: both; } } + @media (max-width: 620px) { + .item-wrap { + width: calc(99.9% * 1/3 - (30px - 30px * 1/3)); } + .item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + .item-wrap:last-child { + margin-right: 0; } + .item-wrap:nth-child(3n) { + margin-right: 0; + float: right; } + .item-wrap:nth-child(3n + 1) { + clear: both; } } + @media (max-width: 460px) { + .item-wrap { + width: calc(99.9% * 1/2 - (30px - 30px * 1/2)); } + .item-wrap:nth-child(1n) { + float: left; + margin-right: 30px; + clear: none; } + .item-wrap:last-child { + margin-right: 0; } + .item-wrap:nth-child(2n) { + margin-right: 0; + float: right; } + .item-wrap:nth-child(2n + 1) { + clear: both; } } + +.item-image-wrap { + position: relative; + float: left; + max-height: 278px; } + @media (max-width: 860px) { + .item-image-wrap { + width: 120px; + height: auto; } } + @media (max-width: 460px) { + .item-image-wrap { + width: 100px; } } + .item-image-wrap:hover .item-new { + display: block; } + +.item-image { + box-shadow: 0 12px 15px 0 rgba(0, 0, 0, 0.5); } + @media (max-width: 860px) { + .item-image { + width: 100%; + height: auto; } } + +.no-image { + width: 185px; + height: 270px; + background: #484848; + float: left; + box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); } + +.item-content { + float: left; + width: 100%; + margin: 20px 0 0 0; } + @media (max-width: 620px) { + .item-content { + margin: 10px 0 0 0; } } + +.item-year { + float: left; + color: #888; + font-size: 14px; } + .dark .item-year { + color: #626262; } + +.item-title { + color: #484848; + clear: both; + font-size: 17px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 100%; + text-decoration: none; + float: left; } + .dark .item-title { + color: #717171; } + .item-title:hover { + color: #f1309a; } + .item-title:active { + color: #895bff; } + +.item-rating { + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.7); + border-radius: 25px; } + .logged .item-rating { + cursor: pointer; + -webkit-transition: background 0.2s ease 0s, -webkit-transform 0.2s ease 0s; + transition: background 0.2s ease 0s, -webkit-transform 0.2s ease 0s; + transition: transform 0.2s ease 0s, background 0.2s ease 0s; + transition: transform 0.2s ease 0s, background 0.2s ease 0s, -webkit-transform 0.2s ease 0s; } + .logged .item-rating:hover { + -webkit-transform: translate(-50%, -50%) scale(1.2); + transform: translate(-50%, -50%) scale(1.2); } + .logged .item-rating:active { + -webkit-transform: translate(-50%, -50%) scale(1.1); + transform: translate(-50%, -50%) scale(1.1); } + +.rating-1 { + background: #6bb01a; } + .rating-1 .icon-rating { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAmVBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VHQRUAAAAMnRSTlMAZ/PpLKeVAvni3djBsKxNJQXsnoR5cEY5GwiyFxMPzcrFupKRiIF9al1XUjAg0M+iYSDJ8foAAAEsSURBVEjH7dLJcoMwDAZgxcHBNjthCRCy70AWvf/DNaSd6TTUQ3Xpif+gA8Mnjy3BkCG/5aLkfkESga3uyE0Kya8uxDijkFJyMMSJQiqsoBYjgjBttQAPUwKZYQywZSWBcNZALl3SIVFbHpSbhBnAiRnm3Df8Pw30hMmzxshtxQSztlmv8LBox15b49X0mEQFruY9ombXz7ZZ87VumGiXZDR9JlqHDfzIgkU6ckCplBKdnhVqt2Ds5EEQeHh+++7LjY6Eu9cP3Z57pj1l0lajS7ikEk9EVJLimUrmeKSSGD0i8YQbEMkZZ9A3l8f7UvhaMnbN1/scstL8vvtR8EBL9mgtb0uGiKFlbwrH4XduM3RL0CZPHMcpJukl3rmb9Wp5s6S13qYmDBnyn/kALc4Y1yVSRigAAAAASUVORK5CYII=); } + +.rating-2 { + background: #da9527; } + .rating-2 .icon-rating { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAmVBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VHQRUAAAAMnRSTlMA6mcs9KeVAvrg28GwrE0lBeXWnoR5cEY5GwjQshcTD/HNysW6kpGIgX1qXVdSMCCiYeQtcuIAAAExSURBVEjH7ZTJboMwFEUN2MHMgTBDyMwMSd7/f1yl0qq4rWXULrLhrLhPHD35WjJaWfknW7vpfPd4lf1wv+h/J7YAgJLKBQznRGwUBIAG+8hGyBkOPdyEhmrRurO/cu4dREoEDZN97IiUG2YPHFJFpFwMNjfiLR5h804T1qw92Hw2VISKSG5jlafo7Ja7RJSnhYFSILzqMpOJiQcYtJs9KgFUHOVksnkM2jh9/3poHOWc/zY9DMTSdV7J15+ze6CDlhk9R7ka3yeJfwRjKNIt4mB5bJlqKAGZCuZRHgtmRQ5GLLjKAJL5KTJoVSSgh/opf9CFEraRkAjmXEYkZoMjR5lwbOqjBeSn2Sug75YoZjZTtGXKH7bMrjJ1FykhWOVmojRBXqKklSt94tYpWll5CW8+/RkqJQ5a/AAAAABJRU5ErkJggg==); } + +.rating-3 { + background: #de2020; } + .rating-3 .icon-rating { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAmVBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VHQRUAAAAMnRSTlMAZ/PpLKeVAvni3djBsKxNJQXsnoR5cEY5GwiyFxMPzcrFupKRiIF9al1XUjAg0M+iYSDJ8foAAAEpSURBVEjH7dHJboMwEIDhwcHBNjuBsJN9Jeu8/8MVqkoVigidWxXxH+b2zVgyjI3977K5bdv5ND5HW2e9Wi7upjRXm9h4Q3ZoLu4LhoiBaa1z2+YPbjF0yn4ycdqFMe7T8ndzcRDc7yXBtp0ePqHTHr3+K9N26qhBpxMmVOIKxycSiNClkgIPVBLjiUpcEVIJcDnwL69kx3qv2Jnv++7Lyz257iN7lEopgXPoVqPWRzJt1hSugit0qlgI77uwWwpt6Q89N3cHcjE3WmpOlrPDPMxxWcBQx++1EXJLMcHMTQqDGVaQNpDpRuHpXgV/KcGwHU8gxNkVMulQSIIRwIaVBGJYqgIXYyBUYw0XoVFIKTno4kgh2c2BCBMK8S31QG4ApbOSuwrGProvKtAY16jA8sMAAAAASUVORK5CYII=); } + +.icon-rating { + width: 50px; + height: 50px; + display: block; } + +.item-new { + background: #895bff; + display: none; } + @media (max-width: 860px) { + .item-new { + display: block; } } + +.icon-add { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAElBMVEUAAAD///////////////////8+Uq06AAAABXRSTlMAd0QimW1x1kgAAAAvSURBVDjLYxgFAwOUDHDJhAoMGxlmJSAIdQISCmgyjKEwEIBbZtD5hzYyo2BwAQBfaw9MqbjYdAAAAABJRU5ErkJggg==); + width: 50px; + height: 50px; + display: block; } + +.remove-item { + position: absolute; + bottom: 0; + right: 0; + opacity: 0; + background: #de2020; + padding: 12px; + cursor: pointer; + -webkit-transition: opacity 0.2s ease 0s; + transition: opacity 0.2s ease 0s; } + .dark .remove-item { + background: #b11a1a; } + .remove-item:hover { + opacity: 1; } + +.icon-remove { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAb1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8v0wLRAAAAJHRSTlMADUXQYQhCXfbtuLOwfjMD4tTNtpFqVE9JOysgGdvGvZhxOBR/FYdmAAAAjElEQVQY00XORw7DMAxE0ZEcyXZc497S5/5nNBcS/VfEAwESbl8NYu4H4Pi8b0p1/xUmk0DNWpAA5kiNv/NhIdlAdUmmQKT0b2VjclDqqoL5As2TbZanBlcVyQG4qgeRV9gJZ7tF/5K2ktkEq+R8z6eMkQQKthaAkqmYjQ6R8hkYSw8gUrIBZlcQOnACsrUKvTcbx/wAAAAASUVORK5CYII=); + width: 17px; + height: 17px; + display: block; } + +.fade-enter-active { + -webkit-transition: opacity .5s ease; + transition: opacity .5s ease; + opacity: 1; + visibility: visible; } + +.fade-enter { + opacity: 0; + visibility: hidden; } + +.box { + float: left; + width: 100%; } + .box h2 { + float: left; + width: 100%; + margin: 0 0 30px 0; + color: #895bff; } + +.nothing-found { + float: left; + width: 100%; + font-size: 32px; + margin: 0 0 30px 0; + color: #484848; } + +.load-more-wrap { + float: left; + height: 100px; + position: relative; + width: 100%; } + +.load-more { + float: left; + width: 100%; + padding: 15px; + background: #e1e1e1; + color: #484848; + text-align: center; + font-size: 15px; + cursor: pointer; } + .dark .load-more { + background: #2f2f2f; + color: #626262; } + .load-more:active { + opacity: .8; } + +.login-wrap { + max-width: 320px; + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; } + +.login-wrap:before { + content: ''; + display: table; } + +.login-wrap:after { + content: ''; + display: table; + clear: both; } + @media (max-width: 740px) { + .login-wrap { + width: 100%; } } + +.top-bar { + float: left; + width: 100%; + height: 30px; + background: #f1309a; + background: -webkit-linear-gradient(left, #895bff, #f1309a); + background: linear-gradient(to right, #895bff, #f1309a); } + +.logo-login { + display: block; + margin: 30vh auto 50px auto; } + +.login-form { + float: left; + width: 100%; } + .login-form input[type="text"], + .login-form input[type="password"] { + float: left; + width: 100%; + font-size: 15px; + margin: 0 0 5px 0; + background: #333; + padding: 12px; + color: #fff; + border: 0; } + .login-form input[type="submit"] { + background: #f1309a; + background: -webkit-linear-gradient(left, #895bff, #f1309a); + background: linear-gradient(to right, #895bff, #f1309a); + color: #fff; + font-size: 17px; + border: 0; + text-transform: uppercase; + padding: 8px 20px; + cursor: pointer; } + +.login-error { + float: left; + height: 20px; + width: 100%; + margin: 10px 0; } + .login-error span { + float: left; + color: #de2020; + font-size: 14px; } + +footer { + padding: 40px 0; + width: 100%; + float: left; + background: #f1309a; + background: -webkit-linear-gradient(left, #895bff, #f1309a); + background: linear-gradient(to right, #895bff, #f1309a); } + .dark footer { + opacity: .9; } + +.attribution { + color: #fff; + float: left; } + +.icon-tmdb { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIsAAAASCAMAAABcrt1GAAAAqFBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8j1z1tAAAAN3RSTlMAFQkF4fbStHICifrz5cipbbmSaWHAl2YozO3Xe3VcElBAPDIuJK+heFZFGQzcgjdLOh8b6ZrDl7Z+cAAAA4JJREFUSMfNlNmaokAMhWMBIqA2oogboOKC+9qd93+zOSmKcfzmYqbv+lywpKjkz1KQSF3LrRvH8eYzvJGRpSxcPaU8+pYGm4xeql1Yx//0U9r80nhOonzaGSuic6dzpe+oARfHN0vS6Qwo6tg3+g99sFYQcKV+7ROF2TJn9B0dm9xVb5aUeUY95j39WzuGPrLicbgvwy5DD2Fpcwe3IfONGnXOSNjTD6C0xGpe3rQ2ZmXuZ+aW5HvJTb3ed1Xej9W7y/JxrY15A0vQcwmO3KYT32Hpj/k5pLznDj4cO8tsJ5ao5ynbwyONXNenobsBfRTBbavJzwjcAyRnWE7Bc1jPjH9iO1K0cLfXsePTZTNhu5cQNVkqUGuErVHFAqHAWl9EM9ZePX6pW/d3TAWzTYg7It3biEUzSphrFq0tafVYFNOi+qzBWm2iKXPzxXKAcVixOJFPPvMmcwCVo4/HLsI/mZMt6DLA0goeF00gHEEmuDuaILM18lEndgE2WdY9Sm7wcyDoimIvTsxrT/CikYvFVSAUYxApqjXHsv+al0/MC2gDyfByf/KHxBJnA9QzqKLj0reEJcODXj+DbtXm1kp8DQzLmlwzwFu5++JDl+HBPCUCiw7HvQdVusjxnlcsT6Vndw8WR7YGyPLutfkk7kNqwhphWTBTzTKvWGxEljNpq1BQS8OykEhz06KFdD/0EBkxUXtqaJYRQ47rl+ksinX3LWFx6nN0rVnsHoY6b7NdsYg1Eu99ICiZqQypGhaeuiF2C0v4m2UrF0jXZ1bVJSa6Iw9TF9oF/CbNngfczv9g6esxWuXWG0uCJkiclUIKR8QY1T06ExXy3acEDeWbh0xmTrsL+eaPs7Y0C3WBHJqpXUcnNmrX/zoPT6emOgsa+ublDPoueKReiaSKPRasQcygkyl8goc8hye61F9jTpW0n01kdwMySa7xQB++JPZaV4TugGHDAq32WT9NdstDEZuDlzJUtISlI/M/cBjyUcuJFCklW6x97WRN1cP4QAr1tKjFIjmGAO0AIWJRzyKpXbU8flAh9NBjwrENlr+ULar7Ik336rC85bRaXizQJ2VYYNKWBTVuy4OxrsNyV2UThnupZ7EsPJj7ZX8kTsLEOyzxVAzKVNYbLRmBUauUm7rJEllfGN4TSvQDdGVWxOD5AZITgG5m9AN0r4aJfoRW27hXEv0CB0mulMnbVoIAAAAASUVORK5CYII=); + width: 139px; + height: 18px; + float: left; + margin: 3px 10px 0 0; } + .icon-tmdb:active { + opacity: .6; } + +.icon-github { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAbCAMAAADF2xaWAAAAV1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////+ORg7oAAAAHHRSTlMA6Bo49A3uKaVlybtCd96xb1nWn461qpV/I8FP59NoagAAATZJREFUKM99k+mWgyAMhQPIJovg3jbv/5xDmnFOxx79fmgMl8uSCA2PKNYI/1GTQPTAOCSc/Rh/TN07x1+6xzeiqFrSnkpVRXCq10DYjL+Y0xsz+yqDVxgFROzwii6yx42CPRJekw6LWxO54B2LBN/hHZ2HFe9ZoefALFva52kdwuC2eU+7O64VRiQGC2fsgMTIiqDhGx1Y0R8XY90mgZGbs8c99BDoSdkmnYCZWorUT7KHmXbRvl7k9eDmoLkvVuIM1bDCY0NxoSj03Fqmggy8SqQjS94GtUMEoB2ElqqIornrgRyZudnqpsyIlQ715BLKVDQw2ifJCz/fKSVQRPhGZRSKw9jCIk/j0mfMfxPtQn9MiVZqDVpLG4vLiMtnKWoQXGwjDLeDCPVUJ+9GYQRjxOj8YfADStUy8IOytk4AAAAASUVORK5CYII=); + width: 33px; + height: 27px; + float: right; } + @media (max-width: 860px) { + .icon-github { + float: left; + clear: both; + margin: 30px 0 0 0; } } + .icon-github:active { + opacity: .6; } + +.sub-links { + float: left; + clear: both; } + +.login-btn { + float: left; + color: #fff; + text-decoration: none; + margin: 20px 20px 0 0; } + .login-btn:active { + opacity: .6; } diff --git a/public/assets/app.js b/public/assets/app.js new file mode 100644 index 0000000..f92239d --- /dev/null +++ b/public/assets/app.js @@ -0,0 +1,6225 @@ +webpackJsonp([0],[ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var _extends2 = __webpack_require__(1); + + var _extends3 = _interopRequireDefault(_extends2); + + var _vue = __webpack_require__(39); + + var _vue2 = _interopRequireDefault(_vue); + + var _vuex = __webpack_require__(40); + + var _Header = __webpack_require__(41); + + var _Header2 = _interopRequireDefault(_Header); + + var _Search = __webpack_require__(77); + + var _Search2 = _interopRequireDefault(_Search); + + var _Footer = __webpack_require__(81); + + var _Footer2 = _interopRequireDefault(_Footer); + + var _Login = __webpack_require__(84); + + var _Login2 = _interopRequireDefault(_Login); + + var _routes = __webpack_require__(88); + + var _routes2 = _interopRequireDefault(_routes); + + var _index = __webpack_require__(43); + + var _index2 = _interopRequireDefault(_index); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + __webpack_require__(124); + + var App = new _vue2.default({ + store: _index2.default, + router: _routes2.default, + + created: function created() { + this.checkForUserColorScheme(); + }, + + + computed: (0, _extends3.default)({}, (0, _vuex.mapState)({ + colorScheme: function colorScheme(state) { + return state.colorScheme; + } + })), + + components: { + SiteHeader: _Header2.default, Search: _Search2.default, SiteFooter: _Footer2.default, Login: _Login2.default + }, + + methods: (0, _extends3.default)({}, (0, _vuex.mapActions)(['setColorScheme']), { + checkForUserColorScheme: function checkForUserColorScheme() { + if (!localStorage.getItem('color')) { + localStorage.setItem('color', 'light'); + } + + this.setColorScheme(localStorage.getItem('color')); + } + }) + }); + + App.$mount('#app'); + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + + exports.__esModule = true; + + var _assign = __webpack_require__(2); + + var _assign2 = _interopRequireDefault(_assign); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = _assign2.default || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(3), __esModule: true }; + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(4); + module.exports = __webpack_require__(7).Object.assign; + +/***/ }, +/* 4 */ +/***/ function(module, exports, __webpack_require__) { + + // 19.1.3.1 Object.assign(target, source) + var $export = __webpack_require__(5); + + $export($export.S + $export.F, 'Object', {assign: __webpack_require__(20)}); + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + + var global = __webpack_require__(6) + , core = __webpack_require__(7) + , ctx = __webpack_require__(8) + , hide = __webpack_require__(10) + , PROTOTYPE = 'prototype'; + + var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } + }; + // type bitmap + $export.F = 1; // forced + $export.G = 2; // global + $export.S = 4; // static + $export.P = 8; // proto + $export.B = 16; // bind + $export.W = 32; // wrap + $export.U = 64; // safe + $export.R = 128; // real proto method for `library` + module.exports = $export; + +/***/ }, +/* 6 */ +/***/ function(module, exports) { + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); + if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef + +/***/ }, +/* 7 */ +/***/ function(module, exports) { + + var core = module.exports = {version: '2.4.0'}; + if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef + +/***/ }, +/* 8 */ +/***/ function(module, exports, __webpack_require__) { + + // optional / simple context binding + var aFunction = __webpack_require__(9); + module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; + }; + +/***/ }, +/* 9 */ +/***/ function(module, exports) { + + module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; + }; + +/***/ }, +/* 10 */ +/***/ function(module, exports, __webpack_require__) { + + var dP = __webpack_require__(11) + , createDesc = __webpack_require__(19); + module.exports = __webpack_require__(15) ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); + } : function(object, key, value){ + object[key] = value; + return object; + }; + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + + var anObject = __webpack_require__(12) + , IE8_DOM_DEFINE = __webpack_require__(14) + , toPrimitive = __webpack_require__(18) + , dP = Object.defineProperty; + + exports.f = __webpack_require__(15) ? Object.defineProperty : function defineProperty(O, P, Attributes){ + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if(IE8_DOM_DEFINE)try { + return dP(O, P, Attributes); + } catch(e){ /* empty */ } + if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); + if('value' in Attributes)O[P] = Attributes.value; + return O; + }; + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(13); + module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; + }; + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + + module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = !__webpack_require__(15) && !__webpack_require__(16)(function(){ + return Object.defineProperty(__webpack_require__(17)('div'), 'a', {get: function(){ return 7; }}).a != 7; + }); + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + + // Thank's IE8 for his funny defineProperty + module.exports = !__webpack_require__(16)(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; + }); + +/***/ }, +/* 16 */ +/***/ function(module, exports) { + + module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } + }; + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(13) + , document = __webpack_require__(6).document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); + module.exports = function(it){ + return is ? document.createElement(it) : {}; + }; + +/***/ }, +/* 18 */ +/***/ function(module, exports, __webpack_require__) { + + // 7.1.1 ToPrimitive(input [, PreferredType]) + var isObject = __webpack_require__(13); + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + module.exports = function(it, S){ + if(!isObject(it))return it; + var fn, val; + if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; + if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; + throw TypeError("Can't convert object to primitive value"); + }; + +/***/ }, +/* 19 */ +/***/ function(module, exports) { + + module.exports = function(bitmap, value){ + return { + enumerable : !(bitmap & 1), + configurable: !(bitmap & 2), + writable : !(bitmap & 4), + value : value + }; + }; + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + // 19.1.2.1 Object.assign(target, source, ...) + var getKeys = __webpack_require__(21) + , gOPS = __webpack_require__(36) + , pIE = __webpack_require__(37) + , toObject = __webpack_require__(38) + , IObject = __webpack_require__(25) + , $assign = Object.assign; + + // should work with symbols and should have deterministic property order (V8 bug) + module.exports = !$assign || __webpack_require__(16)(function(){ + var A = {} + , B = {} + , S = Symbol() + , K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function(k){ B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; + }) ? function assign(target, source){ // eslint-disable-line no-unused-vars + var T = toObject(target) + , aLen = arguments.length + , index = 1 + , getSymbols = gOPS.f + , isEnum = pIE.f; + while(aLen > index){ + var S = IObject(arguments[index++]) + , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) + , length = keys.length + , j = 0 + , key; + while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; + } return T; + } : $assign; + +/***/ }, +/* 21 */ +/***/ function(module, exports, __webpack_require__) { + + // 19.1.2.14 / 15.2.3.14 Object.keys(O) + var $keys = __webpack_require__(22) + , enumBugKeys = __webpack_require__(35); + + module.exports = Object.keys || function keys(O){ + return $keys(O, enumBugKeys); + }; + +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { + + var has = __webpack_require__(23) + , toIObject = __webpack_require__(24) + , arrayIndexOf = __webpack_require__(28)(false) + , IE_PROTO = __webpack_require__(32)('IE_PROTO'); + + module.exports = function(object, names){ + var O = toIObject(object) + , i = 0 + , result = [] + , key; + for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while(names.length > i)if(has(O, key = names[i++])){ + ~arrayIndexOf(result, key) || result.push(key); + } + return result; + }; + +/***/ }, +/* 23 */ +/***/ function(module, exports) { + + var hasOwnProperty = {}.hasOwnProperty; + module.exports = function(it, key){ + return hasOwnProperty.call(it, key); + }; + +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + // to indexed object, toObject with fallback for non-array-like ES3 strings + var IObject = __webpack_require__(25) + , defined = __webpack_require__(27); + module.exports = function(it){ + return IObject(defined(it)); + }; + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var cof = __webpack_require__(26); + module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ + return cof(it) == 'String' ? it.split('') : Object(it); + }; + +/***/ }, +/* 26 */ +/***/ function(module, exports) { + + var toString = {}.toString; + + module.exports = function(it){ + return toString.call(it).slice(8, -1); + }; + +/***/ }, +/* 27 */ +/***/ function(module, exports) { + + // 7.2.1 RequireObjectCoercible(argument) + module.exports = function(it){ + if(it == undefined)throw TypeError("Can't call method on " + it); + return it; + }; + +/***/ }, +/* 28 */ +/***/ function(module, exports, __webpack_require__) { + + // false -> Array#indexOf + // true -> Array#includes + var toIObject = __webpack_require__(24) + , toLength = __webpack_require__(29) + , toIndex = __webpack_require__(31); + module.exports = function(IS_INCLUDES){ + return function($this, el, fromIndex){ + var O = toIObject($this) + , length = toLength(O.length) + , index = toIndex(fromIndex, length) + , value; + // Array#includes uses SameValueZero equality algorithm + if(IS_INCLUDES && el != el)while(length > index){ + value = O[index++]; + if(value != value)return true; + // Array#toIndex ignores holes, Array#includes - not + } else for(;length > index; index++)if(IS_INCLUDES || index in O){ + if(O[index] === el)return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + // 7.1.15 ToLength + var toInteger = __webpack_require__(30) + , min = Math.min; + module.exports = function(it){ + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 + }; + +/***/ }, +/* 30 */ +/***/ function(module, exports) { + + // 7.1.4 ToInteger + var ceil = Math.ceil + , floor = Math.floor; + module.exports = function(it){ + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); + }; + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + + var toInteger = __webpack_require__(30) + , max = Math.max + , min = Math.min; + module.exports = function(index, length){ + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); + }; + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + var shared = __webpack_require__(33)('keys') + , uid = __webpack_require__(34); + module.exports = function(key){ + return shared[key] || (shared[key] = uid(key)); + }; + +/***/ }, +/* 33 */ +/***/ function(module, exports, __webpack_require__) { + + var global = __webpack_require__(6) + , SHARED = '__core-js_shared__' + , store = global[SHARED] || (global[SHARED] = {}); + module.exports = function(key){ + return store[key] || (store[key] = {}); + }; + +/***/ }, +/* 34 */ +/***/ function(module, exports) { + + var id = 0 + , px = Math.random(); + module.exports = function(key){ + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); + }; + +/***/ }, +/* 35 */ +/***/ function(module, exports) { + + // IE 8- don't enum bug keys + module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' + ).split(','); + +/***/ }, +/* 36 */ +/***/ function(module, exports) { + + exports.f = Object.getOwnPropertySymbols; + +/***/ }, +/* 37 */ +/***/ function(module, exports) { + + exports.f = {}.propertyIsEnumerable; + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + + // 7.1.13 ToObject(argument) + var defined = __webpack_require__(27); + module.exports = function(it){ + return Object(defined(it)); + }; + +/***/ }, +/* 39 */, +/* 40 */, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(42) + + /* template */ + var __vue_template__ = __webpack_require__(75) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-3", __vue_options__) + } else { + hotAPI.reload("data-v-3", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Header.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _extends2 = __webpack_require__(1); + + var _extends3 = _interopRequireDefault(_extends2); + + var _index = __webpack_require__(43); + + var _index2 = _interopRequireDefault(_index); + + var _vuex = __webpack_require__(40); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = { + created: function created() { + this.checkForUserFilter(); + }, + + + computed: (0, _extends3.default)({}, (0, _vuex.mapState)({ + userFilter: function userFilter(state) { + return state.userFilter; + }, + colorScheme: function colorScheme(state) { + return state.colorScheme; + } + }), { + root: function root() { + return config.uri; + } + }), + + methods: (0, _extends3.default)({}, (0, _vuex.mapActions)(['setColorScheme', 'loadItems']), (0, _vuex.mapMutations)(['SET_USER_FILTER']), { + toggleColorScheme: function toggleColorScheme() { + var color = this.colorScheme == 'light' ? 'dark' : 'light'; + + this.setColorScheme(color); + }, + checkForUserFilter: function checkForUserFilter() { + if (!localStorage.getItem('filter')) { + localStorage.setItem('filter', 'created_at'); + } + + this.SET_USER_FILTER(localStorage.getItem('filter')); + }, + setUserFilter: function setUserFilter(type) { + localStorage.setItem('filter', type); + this.SET_USER_FILTER(type); + this.loadItems(type); + } + }) + }; + +/***/ }, +/* 43 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _vue = __webpack_require__(39); + + var _vue2 = _interopRequireDefault(_vue); + + var _vuex = __webpack_require__(40); + + var _vuex2 = _interopRequireDefault(_vuex); + + var _actions = __webpack_require__(44); + + var actions = _interopRequireWildcard(_actions); + + var _mutations = __webpack_require__(46); + + var _mutations2 = _interopRequireDefault(_mutations); + + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + _vue2.default.use(_vuex2.default); + + exports.default = new _vuex2.default.Store({ + state: { + items: [], + searchTitle: '', + userFilter: '', + loading: false, + clickedMoreLoading: false, + paginator: null, + colorScheme: '' + }, + mutations: _mutations2.default, + actions: actions + }); + +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.loadItems = loadItems; + exports.loadMoreItems = loadMoreItems; + exports.setSearchTitle = setSearchTitle; + exports.setColorScheme = setColorScheme; + + var _vue = __webpack_require__(39); + + var _vue2 = _interopRequireDefault(_vue); + + var _vueResource = __webpack_require__(45); + + var _vueResource2 = _interopRequireDefault(_vueResource); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + _vue2.default.use(_vueResource2.default); + + function loadItems(_ref, filter) { + var commit = _ref.commit; + + commit('SET_LOADING', true); + _vue2.default.http.get(config.api + '/items/' + filter).then(function (value) { + var _value$data = value.data; + var data = _value$data.data; + var next_page_url = _value$data.next_page_url; + + + commit('SET_ITEMS', data); + commit('SET_PAGINATOR', next_page_url); + + setTimeout(function () { + commit('SET_LOADING', false); + }, 500); + }, function (error) { + if (error.status == 404) { + window.location.href = config.url; + } + }); + } + + function loadMoreItems(_ref2, next_page_url) { + var commit = _ref2.commit; + + commit('SET_CLICKED_LOADING', true); + _vue2.default.http.get(next_page_url).then(function (value) { + var _value$data2 = value.data; + var data = _value$data2.data; + var next_page_url = _value$data2.next_page_url; + + + commit('SET_PAGINATOR', next_page_url); + + setTimeout(function () { + commit('PUSH_TO_ITEMS', data); + commit('SET_CLICKED_LOADING', false); + }, 500); + }); + } + + function setSearchTitle(_ref3, title) { + var commit = _ref3.commit; + + commit('SET_SEARCH_TITLE', title); + } + + function setColorScheme(_ref4, color) { + var commit = _ref4.commit; + + localStorage.setItem('color', color); + commit('SET_COLOR_SCHEME', color); + } + +/***/ }, +/* 45 */, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _defineProperty2 = __webpack_require__(47); + + var _defineProperty3 = _interopRequireDefault(_defineProperty2); + + var _toConsumableArray2 = __webpack_require__(51); + + var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); + + var _type$SET_SEARCH_TITL; + + var _types = __webpack_require__(74); + + var type = _interopRequireWildcard(_types); + + function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = (_type$SET_SEARCH_TITL = {}, (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_SEARCH_TITLE, function (state, title) { + state.searchTitle = title; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_USER_FILTER, function (state, filter) { + state.userFilter = filter; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_ITEMS, function (state, items) { + state.items = items; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.PUSH_TO_ITEMS, function (state, items) { + var _state$items; + + (_state$items = state.items).push.apply(_state$items, (0, _toConsumableArray3.default)(items)); + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_LOADING, function (state, loading) { + state.loading = loading; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_PAGINATOR, function (state, data) { + state.paginator = data; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_CLICKED_LOADING, function (state, loading) { + state.clickedMoreLoading = loading; + }), (0, _defineProperty3.default)(_type$SET_SEARCH_TITL, type.SET_COLOR_SCHEME, function (state, color) { + state.colorScheme = color; + }), _type$SET_SEARCH_TITL); + +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + + exports.__esModule = true; + + var _defineProperty = __webpack_require__(48); + + var _defineProperty2 = _interopRequireDefault(_defineProperty); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = function (obj, key, value) { + if (key in obj) { + (0, _defineProperty2.default)(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + }; + +/***/ }, +/* 48 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(49), __esModule: true }; + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(50); + var $Object = __webpack_require__(7).Object; + module.exports = function defineProperty(it, key, desc){ + return $Object.defineProperty(it, key, desc); + }; + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + + var $export = __webpack_require__(5); + // 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) + $export($export.S + $export.F * !__webpack_require__(15), 'Object', {defineProperty: __webpack_require__(11).f}); + +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + + exports.__esModule = true; + + var _from = __webpack_require__(52); + + var _from2 = _interopRequireDefault(_from); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { + arr2[i] = arr[i]; + } + + return arr2; + } else { + return (0, _from2.default)(arr); + } + }; + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(53), __esModule: true }; + +/***/ }, +/* 53 */ +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(54); + __webpack_require__(67); + module.exports = __webpack_require__(7).Array.from; + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var $at = __webpack_require__(55)(true); + + // 21.1.3.27 String.prototype[@@iterator]() + __webpack_require__(56)(String, 'String', function(iterated){ + this._t = String(iterated); // target + this._i = 0; // next index + // 21.1.5.2.1 %StringIteratorPrototype%.next() + }, function(){ + var O = this._t + , index = this._i + , point; + if(index >= O.length)return {value: undefined, done: true}; + point = $at(O, index); + this._i += point.length; + return {value: point, done: false}; + }); + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + var toInteger = __webpack_require__(30) + , defined = __webpack_require__(27); + // true -> String#at + // false -> String#codePointAt + module.exports = function(TO_STRING){ + return function(that, pos){ + var s = String(defined(that)) + , i = toInteger(pos) + , l = s.length + , a, b; + if(i < 0 || i >= l)return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; + }; + +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var LIBRARY = __webpack_require__(57) + , $export = __webpack_require__(5) + , redefine = __webpack_require__(58) + , hide = __webpack_require__(10) + , has = __webpack_require__(23) + , Iterators = __webpack_require__(59) + , $iterCreate = __webpack_require__(60) + , setToStringTag = __webpack_require__(64) + , getPrototypeOf = __webpack_require__(66) + , ITERATOR = __webpack_require__(65)('iterator') + , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` + , FF_ITERATOR = '@@iterator' + , KEYS = 'keys' + , VALUES = 'values'; + + var returnThis = function(){ return this; }; + + module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ + $iterCreate(Constructor, NAME, next); + var getMethod = function(kind){ + if(!BUGGY && kind in proto)return proto[kind]; + switch(kind){ + case KEYS: return function keys(){ return new Constructor(this, kind); }; + case VALUES: return function values(){ return new Constructor(this, kind); }; + } return function entries(){ return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator' + , DEF_VALUES = DEFAULT == VALUES + , VALUES_BUG = false + , proto = Base.prototype + , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] + , $default = $native || getMethod(DEFAULT) + , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined + , $anyNative = NAME == 'Array' ? proto.entries || $native : $native + , methods, key, IteratorPrototype; + // Fix native + if($anyNative){ + IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); + if(IteratorPrototype !== Object.prototype){ + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if(DEF_VALUES && $native && $native.name !== VALUES){ + VALUES_BUG = true; + $default = function values(){ return $native.call(this); }; + } + // Define iterator + if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if(DEFAULT){ + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if(FORCED)for(key in methods){ + if(!(key in proto))redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; + }; + +/***/ }, +/* 57 */ +/***/ function(module, exports) { + + module.exports = true; + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(10); + +/***/ }, +/* 59 */ +/***/ function(module, exports) { + + module.exports = {}; + +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var create = __webpack_require__(61) + , descriptor = __webpack_require__(19) + , setToStringTag = __webpack_require__(64) + , IteratorPrototype = {}; + + // 25.1.2.1.1 %IteratorPrototype%[@@iterator]() + __webpack_require__(10)(IteratorPrototype, __webpack_require__(65)('iterator'), function(){ return this; }); + + module.exports = function(Constructor, NAME, next){ + Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)}); + setToStringTag(Constructor, NAME + ' Iterator'); + }; + +/***/ }, +/* 61 */ +/***/ function(module, exports, __webpack_require__) { + + // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) + var anObject = __webpack_require__(12) + , dPs = __webpack_require__(62) + , enumBugKeys = __webpack_require__(35) + , IE_PROTO = __webpack_require__(32)('IE_PROTO') + , Empty = function(){ /* empty */ } + , PROTOTYPE = 'prototype'; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var createDict = function(){ + // Thrash, waste and sodomy: IE GC bug + var iframe = __webpack_require__(17)('iframe') + , i = enumBugKeys.length + , lt = '<' + , gt = '>' + , iframeDocument; + iframe.style.display = 'none'; + __webpack_require__(63).appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); + }; + + module.exports = Object.create || function create(O, Properties){ + var result; + if(O !== null){ + Empty[PROTOTYPE] = anObject(O); + result = new Empty; + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); + }; + + +/***/ }, +/* 62 */ +/***/ function(module, exports, __webpack_require__) { + + var dP = __webpack_require__(11) + , anObject = __webpack_require__(12) + , getKeys = __webpack_require__(21); + + module.exports = __webpack_require__(15) ? Object.defineProperties : function defineProperties(O, Properties){ + anObject(O); + var keys = getKeys(Properties) + , length = keys.length + , i = 0 + , P; + while(length > i)dP.f(O, P = keys[i++], Properties[P]); + return O; + }; + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(6).document && document.documentElement; + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + var def = __webpack_require__(11).f + , has = __webpack_require__(23) + , TAG = __webpack_require__(65)('toStringTag'); + + module.exports = function(it, tag, stat){ + if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag}); + }; + +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { + + var store = __webpack_require__(33)('wks') + , uid = __webpack_require__(34) + , Symbol = __webpack_require__(6).Symbol + , USE_SYMBOL = typeof Symbol == 'function'; + + var $exports = module.exports = function(name){ + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); + }; + + $exports.store = store; + +/***/ }, +/* 66 */ +/***/ function(module, exports, __webpack_require__) { + + // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) + var has = __webpack_require__(23) + , toObject = __webpack_require__(38) + , IE_PROTO = __webpack_require__(32)('IE_PROTO') + , ObjectProto = Object.prototype; + + module.exports = Object.getPrototypeOf || function(O){ + O = toObject(O); + if(has(O, IE_PROTO))return O[IE_PROTO]; + if(typeof O.constructor == 'function' && O instanceof O.constructor){ + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; + }; + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var ctx = __webpack_require__(8) + , $export = __webpack_require__(5) + , toObject = __webpack_require__(38) + , call = __webpack_require__(68) + , isArrayIter = __webpack_require__(69) + , toLength = __webpack_require__(29) + , createProperty = __webpack_require__(70) + , getIterFn = __webpack_require__(71); + + $export($export.S + $export.F * !__webpack_require__(73)(function(iter){ Array.from(iter); }), 'Array', { + // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) + from: function from(arrayLike/*, mapfn = undefined, thisArg = undefined*/){ + var O = toObject(arrayLike) + , C = typeof this == 'function' ? this : Array + , aLen = arguments.length + , mapfn = aLen > 1 ? arguments[1] : undefined + , mapping = mapfn !== undefined + , index = 0 + , iterFn = getIterFn(O) + , length, result, step, iterator; + if(mapping)mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); + // if object isn't iterable or it's array with default iterator - use simple case + if(iterFn != undefined && !(C == Array && isArrayIter(iterFn))){ + for(iterator = iterFn.call(O), result = new C; !(step = iterator.next()).done; index++){ + createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value); + } + } else { + length = toLength(O.length); + for(result = new C(length); length > index; index++){ + createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); + } + } + result.length = index; + return result; + } + }); + + +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { + + // call something on iterator step with safe closing on error + var anObject = __webpack_require__(12); + module.exports = function(iterator, fn, value, entries){ + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch(e){ + var ret = iterator['return']; + if(ret !== undefined)anObject(ret.call(iterator)); + throw e; + } + }; + +/***/ }, +/* 69 */ +/***/ function(module, exports, __webpack_require__) { + + // check on default Array iterator + var Iterators = __webpack_require__(59) + , ITERATOR = __webpack_require__(65)('iterator') + , ArrayProto = Array.prototype; + + module.exports = function(it){ + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); + }; + +/***/ }, +/* 70 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var $defineProperty = __webpack_require__(11) + , createDesc = __webpack_require__(19); + + module.exports = function(object, index, value){ + if(index in object)$defineProperty.f(object, index, createDesc(0, value)); + else object[index] = value; + }; + +/***/ }, +/* 71 */ +/***/ function(module, exports, __webpack_require__) { + + var classof = __webpack_require__(72) + , ITERATOR = __webpack_require__(65)('iterator') + , Iterators = __webpack_require__(59); + module.exports = __webpack_require__(7).getIteratorMethod = function(it){ + if(it != undefined)return it[ITERATOR] + || it['@@iterator'] + || Iterators[classof(it)]; + }; + +/***/ }, +/* 72 */ +/***/ function(module, exports, __webpack_require__) { + + // getting tag from 19.1.3.6 Object.prototype.toString() + var cof = __webpack_require__(26) + , TAG = __webpack_require__(65)('toStringTag') + // ES3 wrong here + , ARG = cof(function(){ return arguments; }()) == 'Arguments'; + + // fallback for IE11 Script Access Denied error + var tryGet = function(it, key){ + try { + return it[key]; + } catch(e){ /* empty */ } + }; + + module.exports = function(it){ + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; + }; + +/***/ }, +/* 73 */ +/***/ function(module, exports, __webpack_require__) { + + var ITERATOR = __webpack_require__(65)('iterator') + , SAFE_CLOSING = false; + + try { + var riter = [7][ITERATOR](); + riter['return'] = function(){ SAFE_CLOSING = true; }; + Array.from(riter, function(){ throw 2; }); + } catch(e){ /* empty */ } + + module.exports = function(exec, skipClosing){ + if(!skipClosing && !SAFE_CLOSING)return false; + var safe = false; + try { + var arr = [7] + , iter = arr[ITERATOR](); + iter.next = function(){ return {done: safe = true}; }; + arr[ITERATOR] = function(){ return iter; }; + exec(arr); + } catch(e){ /* empty */ } + return safe; + }; + +/***/ }, +/* 74 */ +/***/ function(module, exports) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var SET_SEARCH_TITLE = exports.SET_SEARCH_TITLE = 'SET_SEARCH_TITLE'; + var SET_USER_FILTER = exports.SET_USER_FILTER = 'SET_USER_FILTER'; + var SET_ITEMS = exports.SET_ITEMS = 'SET_ITEMS'; + var PUSH_TO_ITEMS = exports.PUSH_TO_ITEMS = 'PUSH_TO_ITEMS'; + var SET_LOADING = exports.SET_LOADING = 'SET_LOADING'; + var SET_PAGINATOR = exports.SET_PAGINATOR = 'SET_PAGINATOR'; + var SET_CLICKED_LOADING = exports.SET_CLICKED_LOADING = 'SET_CLICKED_LOADING'; + var SET_COLOR_SCHEME = exports.SET_COLOR_SCHEME = 'SET_COLOR_SCHEME'; + +/***/ }, +/* 75 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('header', [_h('div', { + staticClass: "wrap" + }, [_h('router-link', { + staticClass: "logo", + attrs: { + "to": "/" + } + }, [_m(0)]), " ", _h('span', { + staticClass: "sort-wrap" + }, [_h('i', { + staticClass: "icon-sort-time", + class: { + active: userFilter == 'created_at' + }, + on: { + "click": function($event) { + setUserFilter('created_at') + } + } + }), " ", _h('i', { + staticClass: "icon-sort-star", + class: { + active: userFilter == 'rating' + }, + on: { + "click": function($event) { + setUserFilter('rating') + } + } + }), " ", _h('span', { + staticClass: "icon-constrast", + on: { + "click": function($event) { + toggleColorScheme() + } + } + }, [_m(1)])])])]) + }},staticRenderFns: [function (){with(this) { + return _h('img', { + attrs: { + "src": __webpack_require__(76), + "alt": "Flox", + "width": "108", + "height": "32" + } + }) + }},function (){with(this) { + return _h('i') + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-3", module.exports) + } + } + +/***/ }, +/* 76 */ +/***/ function(module, exports) { + + module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAAAgCAMAAADAIm3oAAAAilBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2N2iNAAAALXRSTlMA3VUzEYcLwLuZj0R37swdFCks88gh69G2q19TA8M5+Ahm2KiinWg75n597FBo4OziAAACOklEQVRIx71Xf3eqMAxtocUCFlDHlCnqfvq29/L9v947FtLMyCadx90/PBporklvL0H8EMlsrZvVcrlq9HqWiFuielstwGOxeqvErVB9SGCQHyPpcnkG3YXFINZPMICnNd1RyJStia3M3ZcIzqBdeJAsyeALZIlPDRCdriqgp4/ARgzxl2SlAY+7V61f7+i3KfGuKdj686oUpEIylvWbcOlz32fzxFU6z+49u2czYAQhB8hFMJlqMe9kTtH5BKOt6kO1hSmtkqBFMNnmGbO+JCf7+ILx500fegSIqcxChJNNfV0JUw3WRvU0UHheW4eTbRe4X9hDtS37TuK+LbbUuxSl+SiCyTYTL3IMzUDqrsjMF71hqiigEeFkD5hvN/NesgOYKEe7w6sPeFGDVcdPqcLJ1NL/+T3G/vk6977spaKTbLC+QDIqDFLPXxx//im7c0ulkZFMcecCycgqtCOqVVSAg9OEJmM5Ua/kWUEyjCA77FCbnKz9bImQczIOOaKNNYp9qI0kSDCczMYMFwWCYv9WIEpCg7Z1pfQrl35Q+mRTaFtXH+pESxg81CSPGG3rCrv625/q8nAoeythdoU2hbZ1jRGb/emFvWFG3B1pVEmEsRs9YkQKVuG3ENcnVJcenhWthpzVeLOxoLZup8i2gsn4wNMeB56WDTwdDC4mXQaQBY1ylJ241QUybixqxJDK+0ZdvUDGoVEm7+fj93snDbQpc54swvF73FSuR75YaClrni2V2MjfemX6D0AKmiHCtfAOAAAAAElFTkSuQmCC" + +/***/ }, +/* 77 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(78) + + /* template */ + var __vue_template__ = __webpack_require__(80) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-1", __vue_options__) + } else { + hotAPI.reload("data-v-1", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Search.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 78 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _helper = __webpack_require__(79); + + var _helper2 = _interopRequireDefault(_helper); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = { + mixins: [_helper2.default], + + mounted: function mounted() { + this.initSticky(); + }, + data: function data() { + return { + sticky: false + }; + }, + + + computed: { + algolia: function algolia() { + return config.scoutDriver == 'algolia' && this.$route.query.q; + }, + + + title: { + get: function get() { + return this.$store.state.searchTitle; + }, + set: function set(title) { + this.$store.commit('SET_SEARCH_TITLE', title); + } + }, + + placeholder: function placeholder() { + return config.auth ? 'Search or add movie' : 'Search movie'; + } + }, + + methods: { + initSticky: function initSticky() { + var _this = this; + + var height = document.querySelector('header').scrollHeight; + + window.onscroll = function () { + _this.sticky = document.body.scrollTop + document.documentElement.scrollTop > height; + }; + }, + search: function search() { + if (this.title != '') { + this.$router.push({ + path: '/search?q=' + this.title + }); + } + } + } + }; + +/***/ }, +/* 79 */ +/***/ function(module, exports) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.default = { + methods: { + scrollToTop: function scrollToTop() { + var scrollDuration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300; + + var cosParameter = window.scrollY / 2; + var scrollCount = 0; + var oldTimestamp = performance.now(); + + function step(newTimestamp) { + scrollCount += Math.PI / (scrollDuration / (newTimestamp - oldTimestamp)); + + if (scrollCount >= Math.PI) window.scrollTo(0, 0); + if (window.scrollY === 0) return; + + window.scrollTo(0, Math.round(cosParameter + cosParameter * Math.cos(scrollCount))); + oldTimestamp = newTimestamp; + window.requestAnimationFrame(step); + } + + window.requestAnimationFrame(step); + } + } + }; + +/***/ }, +/* 80 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('section', { + staticClass: "search-wrap", + class: { + sticky: sticky + } + }, [_h('div', { + staticClass: "wrap" + }, [_h('form', { + staticClass: "search-form", + on: { + "submit": function($event) { + $event.preventDefault(); + search() + } + } + }, [_h('router-link', { + attrs: { + "to": "/" + } + }, [_h('i', { + staticClass: "icon-logo-small", + on: { + "click": function($event) { + scrollToTop() + } + } + })]), " ", _m(0), " ", _h('input', { + directives: [{ + name: "model", + value: (title), + expression: "title" + }], + staticClass: "search-input", + attrs: { + "type": "text", + "placeholder": placeholder, + "autofocus": "" + }, + domProps: { + "value": _s(title) + }, + on: { + "input": function($event) { + if ($event.target.composing) return; + title = $event.target.value + } + } + }), " ", (algolia) ? _h('i', { + staticClass: "icon-algolia" + }) : _e()])])]) + }},staticRenderFns: [function (){with(this) { + return _h('i', { + staticClass: "icon-search" + }) + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-1", module.exports) + } + } + +/***/ }, +/* 81 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(82) + + /* template */ + var __vue_template__ = __webpack_require__(83) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-4", __vue_options__) + } else { + hotAPI.reload("data-v-4", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Footer.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 82 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _extends2 = __webpack_require__(1); + + var _extends3 = _interopRequireDefault(_extends2); + + var _vuex = __webpack_require__(40); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = { + data: function data() { + return { + auth: config.auth, + logout: config.api + '/logout', + login: config.url + '/login', + settings: config.url + '/settings' + }; + }, + + + computed: (0, _extends3.default)({}, (0, _vuex.mapState)({ + loading: function loading(state) { + return state.loading; + } + })) + }; + +/***/ }, +/* 83 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('footer', { + directives: [{ + name: "show", + value: (!loading), + expression: " ! loading" + }] + }, [_h('div', { + staticClass: "wrap" + }, [_m(0), " ", _m(1), " ", _h('div', { + staticClass: "sub-links" + }, [(auth) ? _h('a', { + staticClass: "login-btn", + attrs: { + "href": settings + } + }, ["Settings"]) : _e(), " ", (auth) ? _h('a', { + staticClass: "login-btn", + attrs: { + "href": logout + } + }, ["Logout"]) : _e(), " ", (!auth) ? _h('a', { + staticClass: "login-btn", + attrs: { + "href": login + } + }, ["Login"]) : _e()])])]) + }},staticRenderFns: [function (){with(this) { + return _h('span', { + staticClass: "attribution" + }, [_h('a', { + attrs: { + "href": "https://www.themoviedb.org/", + "target": "_blank" + } + }, [_h('i', { + staticClass: "icon-tmdb" + })]), "\n This product uses the TMDb API but is not endorsed or certified by TMDb\n "]) + }},function (){with(this) { + return _h('a', { + staticClass: "icon-github", + attrs: { + "href": "https://github.com/devfake/flox", + "target": "_blank" + } + }) + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-4", module.exports) + } + } + +/***/ }, +/* 84 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(85) + + /* template */ + var __vue_template__ = __webpack_require__(86) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-2", __vue_options__) + } else { + hotAPI.reload("data-v-2", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Login.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 85 */ +/***/ function(module, exports) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.default = { + created: function created() { + document.body.className += ' dark'; + }, + data: function data() { + return { + username: '', + password: '', + error: false, + errorShake: false + }; + }, + + + methods: { + login: function login() { + var _this = this; + + this.error = false; + var username = this.username; + var password = this.password; + + this.$http.post(config.api + '/login', { username: username, password: password }).then(function (value) { + window.location.href = config.url; + }, function (error) { + _this.error = true; + _this.errorShake = true; + + setTimeout(function () { + _this.errorShake = false; + }, 500); + }); + } + } + }; + +/***/ }, +/* 86 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('div', [_m(0), " ", _h('div', { + staticClass: "login-wrap" + }, [_m(1), " ", _h('form', { + staticClass: "login-form", + on: { + "submit": function($event) { + $event.preventDefault(); + login() + } + } + }, [_h('input', { + directives: [{ + name: "model", + value: (username), + expression: "username" + }], + attrs: { + "type": "text", + "placeholder": "Username", + "autofocus": "" + }, + domProps: { + "value": _s(username) + }, + on: { + "input": function($event) { + if ($event.target.composing) return; + username = $event.target.value + } + } + }), " ", _h('input', { + directives: [{ + name: "model", + value: (password), + expression: "password" + }], + attrs: { + "type": "password", + "placeholder": "Password" + }, + domProps: { + "value": _s(password) + }, + on: { + "input": function($event) { + if ($event.target.composing) return; + password = $event.target.value + } + } + }), " ", _h('span', { + staticClass: "login-error" + }, [(error) ? _h('span', ["Wrong username or password"]) : _e()]), " ", _h('input', { + class: errorShake ? 'shake-horizontal shake-constant' : '', + attrs: { + "type": "submit", + "value": "Sign In" + } + })])])]) + }},staticRenderFns: [function (){with(this) { + return _h('span', { + staticClass: "top-bar" + }) + }},function (){with(this) { + return _h('img', { + staticClass: "logo-login", + attrs: { + "src": __webpack_require__(87), + "alt": "Flox", + "width": "108", + "height": "32" + } + }) + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-2", module.exports) + } + } + +/***/ }, +/* 87 */ +/***/ function(module, exports) { + + module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGwAAAAgCAMAAADAIm3oAAACE1BMVEUAAACKW/+cU+yaVO6KW/7GQsSQWPnnNKToNKOSV/e8Rs7QPruMWv2PWfqhUejGQsXEQsaqTeDoNKS7Rs+TV/bkNae/RcvtMZ6+RczGQsWVVvSlT+SrTd7sMp/wMJvtMZ7nNKS/RcvNP77QPrvTPbjNP73uMZ2RWPigUenhN6u6RtDSPbnGQsSwStqxStnARMrPPrvVPLbLQL/GQsTqM6LRPbrGQsTwMJy4R9LLQL/TPLe0SdbKQMHWO7XnNKStTN3eOK7QPruSV/fEQ8azSdfjNqjoNKPARMvmNaXmNKXEQsbdOK+6RtDuMZ29Rc3sMp/ARMnrM6DiNqntMZ3vMJy5R9HTPbiwS9m/RcvbObCKW/66R9DRPbnLQL+JW//IQcKtTNzdOK7oNKPfN6zXO7PJQcHYOrLKQMC1SdTqM6LEQ8axStjZOrG8Rs25R9HjNqjmNKWWVvLTPbi6R9CwS9m8Rs3PPrvlNabrMqDjNqivS9rNP73cOa/ARMrARMnGQsPBRMicU+zEQ8bfOKztMZ23SNPVPLa1SdXYOrPKQMG6R9GbU+2JW//RPbq8Rs7EQ8fBRMnPPrzWO7SwS9rGQsOyStfIQcLTPbixStjFQsXZOrHLQL/vMZyTV/boNKPrM6HtMZ6MWv2+RczbObDiNqmPWPm/RcvNP73cOa/lNafmNKWtTN2KW/6kUOaeUurdOK6pTeCVJkKBAAAAhXRSTlMAVd1V3QszETNVER3d3TMDhzMhFN27U0QpCN3d3d3dzEQsLCkU7+7d3d3b29HIwsG/vrarq56dmY+Pj4eHendfX1NEOh3u7uvdzMvBwLu4mY+Hd3dV+Pjz8/Pu7Ovm3d3R0czKyMbDwLu7tqioopmZmYeHfXdoaGZmVTk5OSH4+PPu3Ydmpzv5zwAAAydJREFUSMe9l+dX01AYxl+R0lpUakspRQsFBCx7FMosIntPF25w4QInoOJmCwVBFI1J1DqSovInmqQ3F9rGtoFTfx96evIhv3Pf3PvkCWwRRWyMpuBaZmZ+QXlVsgJCie5+24mFBYdjdXllevpjSv6DgxAqdHfT579835D9WFzMqAhSd+RsePhujj0caWnR0dFxcbf5y2FhIElM+sy8t2xuLqMKMP2WQfBElRpvAJ4dr9fWPvN84/gkwMt2zkrKFMXjM1KydxOlCnxrp3MUPEggbIBkvTsEdmEi/imruTqOZU1FGk3RJSybyIsERJezVgubsBHxSlEWDr5Iy2qyJpGsviNRIaw0qSQFyd5cxDa9Uw8bGAjCALJl6uxJJMtJBExSLpJNXVaiS9paxg4iShPRCbJlUdffItlNhcdzLESyqRtR6NIww6gA0UongHzZvfdI1oJc2JaLZB8qAGFlGtG/ETpVK1/28DiSnRJnqK6ORJM8jWQnH4uza2CH3FuTpl+BbFlU9hKSFQMidvlcuXuRpUj2tVkcpJllzcKup60gX1a5hGRHY3GWPF2ZvqIGjuRjSPbzMCA62Tol90uZlPJl6vOirMWIw4Q/1CXAYcwTZRfwvRvJATBTlAHkyypdouwW9jfxsjPCcysUZX/w0lQkaTdR7bAFWRaWlQmiMXVMkzuuHgHHHSzrBxE7SVIm8JKteQdxELLqJ88cDklZM2D6SI8hSgZxXBBjHKvng9jvGMHMrWzAW9Yb4UUwG6SDl/ndIMoG0lpHdQNsf+vrcniZn60PerIPRihKBbD9Q63QvFj1c6jBzpKcx0qhYNxyXKFTHVktxlWyT1yBimWHhcin2wG2E8RtRvDA6BvE0MjqgcdA0z0AIX3FwCBTh3ZKu7zUx+gCvTxxxxplGDMuIHQrAISiFuA39RCIqGiiW6bMt/DkSBQe3EEaYINuglAFlMmvcrhdOT1OV2vgdvV8L2KfG3Xgkop7YxdsRptK2ALIZn9z/OJZX193uVxlQdZvpUUscpgegugR6zf4INTvsEMc+3kO8JQF+WHx0mLRghe2eDTI//bJ9BcGDf91+LWedQAAAABJRU5ErkJggg==" + +/***/ }, +/* 88 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _vue = __webpack_require__(39); + + var _vue2 = _interopRequireDefault(_vue); + + var _vueRouter = __webpack_require__(89); + + var _vueRouter2 = _interopRequireDefault(_vueRouter); + + var _config = __webpack_require__(90); + + var _config2 = _interopRequireDefault(_config); + + var _Content = __webpack_require__(91); + + var _Content2 = _interopRequireDefault(_Content); + + var _SearchContent = __webpack_require__(97); + + var _SearchContent2 = _interopRequireDefault(_SearchContent); + + var _Settings = __webpack_require__(121); + + var _Settings2 = _interopRequireDefault(_Settings); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + window.config = _config2.default; + + _vue2.default.use(_vueRouter2.default); + + exports.default = new _vueRouter2.default({ + mode: 'history', + base: _config2.default.uri, + routes: [{ path: '/', component: _Content2.default }, { path: '/search', component: _SearchContent2.default }, { path: '/settings', component: _Settings2.default }, { path: '*', component: _Content2.default }] + }); + +/***/ }, +/* 89 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * vue-router v2.0.0 + * (c) 2016 Evan You + * @license MIT + */ + (function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.VueRouter = factory()); + }(this, (function () { 'use strict'; + + var View = { + name: 'router-view', + functional: true, + props: { + name: { + type: String, + default: 'default' + } + }, + render: function render (h, ref) { + var props = ref.props; + var children = ref.children; + var parent = ref.parent; + var data = ref.data; + + data.routerView = true + + var route = parent.$route + var cache = parent._routerViewCache || (parent._routerViewCache = {}) + var depth = 0 + var inactive = false + + while (parent) { + if (parent.$vnode && parent.$vnode.data.routerView) { + depth++ + } + if (parent._inactive) { + inactive = true + } + parent = parent.$parent + } + + data.routerViewDepth = depth + var matched = route.matched[depth] + if (!matched) { + return h() + } + + var component = inactive + ? cache[props.name] + : (cache[props.name] = matched.components[props.name]) + + if (!inactive) { + (data.hook || (data.hook = {})).init = function (vnode) { + matched.instances[props.name] = vnode.child + } + } + + return h(component, data, children) + } + } + + /* */ + + function resolvePath ( + relative, + base, + append + ) { + if (relative.charAt(0) === '/') { + return relative + } + + if (relative.charAt(0) === '?' || relative.charAt(0) === '#') { + return base + relative + } + + var stack = base.split('/') + + // remove trailing segment if: + // - not appending + // - appending to trailing slash (last segment is empty) + if (!append || !stack[stack.length - 1]) { + stack.pop() + } + + // resolve relative path + var segments = relative.replace(/^\//, '').split('/') + for (var i = 0; i < segments.length; i++) { + var segment = segments[i] + if (segment === '.') { + continue + } else if (segment === '..') { + stack.pop() + } else { + stack.push(segment) + } + } + + // ensure leading slash + if (stack[0] !== '') { + stack.unshift('') + } + + return stack.join('/') + } + + function parsePath (path) { + var hash = '' + var query = '' + + var hashIndex = path.indexOf('#') + if (hashIndex >= 0) { + hash = path.slice(hashIndex) + path = path.slice(0, hashIndex) + } + + var queryIndex = path.indexOf('?') + if (queryIndex >= 0) { + query = path.slice(queryIndex + 1) + path = path.slice(0, queryIndex) + } + + return { + path: path, + query: query, + hash: hash + } + } + + function cleanPath (path) { + return path.replace(/\/\//g, '/') + } + + /* */ + + function assert (condition, message) { + if (!condition) { + throw new Error(("[vue-router] " + message)) + } + } + + function warn (condition, message) { + if (!condition) { + typeof console !== 'undefined' && console.warn(("[vue-router] " + message)) + } + } + + /* */ + + var encode = encodeURIComponent + var decode = decodeURIComponent + + function resolveQuery ( + query, + extraQuery + ) { + if ( extraQuery === void 0 ) extraQuery = {}; + + if (query) { + var parsedQuery + try { + parsedQuery = parseQuery(query) + } catch (e) { + warn(false, e.message) + parsedQuery = {} + } + for (var key in extraQuery) { + parsedQuery[key] = extraQuery[key] + } + return parsedQuery + } else { + return extraQuery + } + } + + function parseQuery (query) { + var res = Object.create(null) + + query = query.trim().replace(/^(\?|#|&)/, '') + + if (!query) { + return res + } + + query.split('&').forEach(function (param) { + var parts = param.replace(/\+/g, ' ').split('=') + var key = decode(parts.shift()) + var val = parts.length > 0 + ? decode(parts.join('=')) + : null + + if (res[key] === undefined) { + res[key] = val + } else if (Array.isArray(res[key])) { + res[key].push(val) + } else { + res[key] = [res[key], val] + } + }) + + return res + } + + function stringifyQuery (obj) { + var res = obj ? Object.keys(obj).sort().map(function (key) { + var val = obj[key] + + if (val === undefined) { + return '' + } + + if (val === null) { + return encode(key) + } + + if (Array.isArray(val)) { + var result = [] + val.slice().forEach(function (val2) { + if (val2 === undefined) { + return + } + if (val2 === null) { + result.push(encode(key)) + } else { + result.push(encode(key) + '=' + encode(val2)) + } + }) + return result.join('&') + } + + return encode(key) + '=' + encode(val) + }).filter(function (x) { return x.length > 0; }).join('&') : null + return res ? ("?" + res) : '' + } + + /* */ + + function createRoute ( + record, + location, + redirectedFrom + ) { + var route = { + name: location.name || (record && record.name), + meta: (record && record.meta) || {}, + path: location.path || '/', + hash: location.hash || '', + query: location.query || {}, + params: location.params || {}, + fullPath: getFullPath(location), + matched: record ? formatMatch(record) : [] + } + if (redirectedFrom) { + route.redirectedFrom = getFullPath(redirectedFrom) + } + return Object.freeze(route) + } + + // the starting route that represents the initial state + var START = createRoute(null, { + path: '/' + }) + + function formatMatch (record) { + var res = [] + while (record) { + res.unshift(record) + record = record.parent + } + return res + } + + function getFullPath (ref) { + var path = ref.path; + var query = ref.query; if ( query === void 0 ) query = {}; + var hash = ref.hash; if ( hash === void 0 ) hash = ''; + + return (path || '/') + stringifyQuery(query) + hash + } + + var trailingSlashRE = /\/$/ + function isSameRoute (a, b) { + if (b === START) { + return a === b + } else if (!b) { + return false + } else if (a.path && b.path) { + return ( + a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && + a.hash === b.hash && + isObjectEqual(a.query, b.query) + ) + } else if (a.name && b.name) { + return ( + a.name === b.name && + a.hash === b.hash && + isObjectEqual(a.query, b.query) && + isObjectEqual(a.params, b.params) + ) + } else { + return false + } + } + + function isObjectEqual (a, b) { + if ( a === void 0 ) a = {}; + if ( b === void 0 ) b = {}; + + var aKeys = Object.keys(a) + var bKeys = Object.keys(b) + if (aKeys.length !== bKeys.length) { + return false + } + return aKeys.every(function (key) { return String(a[key]) === String(b[key]); }) + } + + function isIncludedRoute (current, target) { + return ( + current.path.indexOf(target.path) === 0 && + (!target.hash || current.hash === target.hash) && + queryIncludes(current.query, target.query) + ) + } + + function queryIncludes (current, target) { + for (var key in target) { + if (!(key in current)) { + return false + } + } + return true + } + + /* */ + + function normalizeLocation ( + raw, + current, + append + ) { + var next = typeof raw === 'string' ? { path: raw } : raw + if (next.name || next._normalized) { + return next + } + + var parsedPath = parsePath(next.path || '') + var basePath = (current && current.path) || '/' + var path = parsedPath.path + ? resolvePath(parsedPath.path, basePath, append) + : (current && current.path) || '/' + var query = resolveQuery(parsedPath.query, next.query) + var hash = next.hash || parsedPath.hash + if (hash && hash.charAt(0) !== '#') { + hash = "#" + hash + } + + return { + _normalized: true, + path: path, + query: query, + hash: hash + } + } + + /* */ + + // work around weird flow bug + var toTypes = [String, Object] + + var Link = { + name: 'router-link', + props: { + to: { + type: toTypes, + required: true + }, + tag: { + type: String, + default: 'a' + }, + exact: Boolean, + append: Boolean, + replace: Boolean, + activeClass: String + }, + render: function render (h) { + var this$1 = this; + + var router = this.$router + var current = this.$route + var to = normalizeLocation(this.to, current, this.append) + var resolved = router.match(to) + var fullPath = resolved.redirectedFrom || resolved.fullPath + var base = router.history.base + var href = base ? cleanPath(base + fullPath) : fullPath + var classes = {} + var activeClass = this.activeClass || router.options.linkActiveClass || 'router-link-active' + var compareTarget = to.path ? createRoute(null, to) : resolved + classes[activeClass] = this.exact + ? isSameRoute(current, compareTarget) + : isIncludedRoute(current, compareTarget) + + var on = { + click: function (e) { + e.preventDefault() + if (this$1.replace) { + router.replace(to) + } else { + router.push(to) + } + } + } + + var data = { + class: classes + } + + if (this.tag === 'a') { + data.on = on + data.attrs = { href: href } + } else { + // find the first child and apply listener and href + var a = findAnchor(this.$slots.default) + if (a) { + var aData = a.data || (a.data = {}) + aData.on = on + var aAttrs = aData.attrs || (aData.attrs = {}) + aAttrs.href = href + } + } + + return h(this.tag, data, this.$slots.default) + } + } + + function findAnchor (children) { + if (children) { + var child + for (var i = 0; i < children.length; i++) { + child = children[i] + if (child.tag === 'a') { + return child + } + if (child.children && (child = findAnchor(child.children))) { + return child + } + } + } + } + + function install (Vue) { + if (install.installed) { return } + install.installed = true + + Object.defineProperty(Vue.prototype, '$router', { + get: function get () { return this.$root._router } + }) + + Object.defineProperty(Vue.prototype, '$route', { + get: function get$1 () { return this.$root._route } + }) + + Vue.mixin({ + beforeCreate: function beforeCreate () { + if (this.$options.router) { + this._router = this.$options.router + this._router.init(this) + Vue.util.defineReactive(this, '_route', this._router.history.current) + } + } + }) + + Vue.component('router-view', View) + Vue.component('router-link', Link) + } + + var __moduleExports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; + }; + + var isarray = __moduleExports + + /** + * Expose `pathToRegexp`. + */ + var index = pathToRegexp + var parse_1 = parse + var compile_1 = compile + var tokensToFunction_1 = tokensToFunction + var tokensToRegExp_1 = tokensToRegExp + + /** + * The main path matching regexp utility. + * + * @type {RegExp} + */ + var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' + ].join('|'), 'g') + + /** + * Parse a string for the raw tokens. + * + * @param {string} str + * @return {!Array} + */ + function parse (str) { + var tokens = [] + var key = 0 + var index = 0 + var path = '' + var res + + while ((res = PATH_REGEXP.exec(str)) != null) { + var m = res[0] + var escaped = res[1] + var offset = res.index + path += str.slice(index, offset) + index = offset + m.length + + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1] + continue + } + + var next = str[index] + var prefix = res[2] + var name = res[3] + var capture = res[4] + var group = res[5] + var modifier = res[6] + var asterisk = res[7] + + // Push the current path onto the tokens. + if (path) { + tokens.push(path) + path = '' + } + + var partial = prefix != null && next != null && next !== prefix + var repeat = modifier === '+' || modifier === '*' + var optional = modifier === '?' || modifier === '*' + var delimiter = res[2] || '/' + var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?') + + tokens.push({ + name: name || key++, + prefix: prefix || '', + delimiter: delimiter, + optional: optional, + repeat: repeat, + partial: partial, + asterisk: !!asterisk, + pattern: escapeGroup(pattern) + }) + } + + // Match any characters still remaining. + if (index < str.length) { + path += str.substr(index) + } + + // If the path exists, push it onto the end. + if (path) { + tokens.push(path) + } + + return tokens + } + + /** + * Compile a string to a template function for the path. + * + * @param {string} str + * @return {!function(Object=, Object=)} + */ + function compile (str) { + return tokensToFunction(parse(str)) + } + + /** + * Prettier encoding of URI path segments. + * + * @param {string} + * @return {string} + */ + function encodeURIComponentPretty (str) { + return encodeURI(str).replace(/[\/?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } + + /** + * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. + * + * @param {string} + * @return {string} + */ + function encodeAsterisk (str) { + return encodeURI(str).replace(/[?#]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) + } + + /** + * Expose a method for transforming tokens into the path function. + */ + function tokensToFunction (tokens) { + // Compile all the tokens into regexps. + var matches = new Array(tokens.length) + + // Compile all the patterns before compilation. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] === 'object') { + matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$') + } + } + + return function (obj, opts) { + var path = '' + var data = obj || {} + var options = opts || {} + var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i] + + if (typeof token === 'string') { + path += token + + continue + } + + var value = data[token.name] + var segment + + if (value == null) { + if (token.optional) { + // Prepend partial segment prefixes. + if (token.partial) { + path += token.prefix + } + + continue + } else { + throw new TypeError('Expected "' + token.name + '" to be defined') + } + } + + if (isarray(value)) { + if (!token.repeat) { + throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') + } + + if (value.length === 0) { + if (token.optional) { + continue + } else { + throw new TypeError('Expected "' + token.name + '" to not be empty') + } + } + + for (var j = 0; j < value.length; j++) { + segment = encode(value[j]) + + if (!matches[i].test(segment)) { + throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') + } + + path += (j === 0 ? token.prefix : token.delimiter) + segment + } + + continue + } + + segment = token.asterisk ? encodeAsterisk(value) : encode(value) + + if (!matches[i].test(segment)) { + throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') + } + + path += token.prefix + segment + } + + return path + } + } + + /** + * Escape a regular expression string. + * + * @param {string} str + * @return {string} + */ + function escapeString (str) { + return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') + } + + /** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {string} group + * @return {string} + */ + function escapeGroup (group) { + return group.replace(/([=!:$\/()])/g, '\\$1') + } + + /** + * Attach the keys as a property of the regexp. + * + * @param {!RegExp} re + * @param {Array} keys + * @return {!RegExp} + */ + function attachKeys (re, keys) { + re.keys = keys + return re + } + + /** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {string} + */ + function flags (options) { + return options.sensitive ? '' : 'i' + } + + /** + * Pull out keys from a regexp. + * + * @param {!RegExp} path + * @param {!Array} keys + * @return {!RegExp} + */ + function regexpToRegexp (path, keys) { + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g) + + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + prefix: null, + delimiter: null, + optional: false, + repeat: false, + partial: false, + asterisk: false, + pattern: null + }) + } + } + + return attachKeys(path, keys) + } + + /** + * Transform an array into a regexp. + * + * @param {!Array} path + * @param {Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function arrayToRegexp (path, keys, options) { + var parts = [] + + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source) + } + + var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)) + + return attachKeys(regexp, keys) + } + + /** + * Create a path regexp from string input. + * + * @param {string} path + * @param {!Array} keys + * @param {!Object} options + * @return {!RegExp} + */ + function stringToRegexp (path, keys, options) { + var tokens = parse(path) + var re = tokensToRegExp(tokens, options) + + // Attach keys back to the regexp. + for (var i = 0; i < tokens.length; i++) { + if (typeof tokens[i] !== 'string') { + keys.push(tokens[i]) + } + } + + return attachKeys(re, keys) + } + + /** + * Expose a function for taking tokens and returning a RegExp. + * + * @param {!Array} tokens + * @param {Object=} options + * @return {!RegExp} + */ + function tokensToRegExp (tokens, options) { + options = options || {} + + var strict = options.strict + var end = options.end !== false + var route = '' + var lastToken = tokens[tokens.length - 1] + var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken) + + // Iterate over the tokens and create our regexp string. + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i] + + if (typeof token === 'string') { + route += escapeString(token) + } else { + var prefix = escapeString(token.prefix) + var capture = '(?:' + token.pattern + ')' + + if (token.repeat) { + capture += '(?:' + prefix + capture + ')*' + } + + if (token.optional) { + if (!token.partial) { + capture = '(?:' + prefix + '(' + capture + '))?' + } else { + capture = prefix + '(' + capture + ')?' + } + } else { + capture = prefix + '(' + capture + ')' + } + + route += capture + } + } + + // In non-strict mode we allow a slash at the end of match. If the path to + // match already ends with a slash, we remove it for consistency. The slash + // is valid at the end of a path match, not in the middle. This is important + // in non-ending mode, where "/test/" shouldn't match "/test//route". + if (!strict) { + route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?' + } + + if (end) { + route += '$' + } else { + // In non-ending mode, we need the capturing groups to match as much as + // possible by using a positive lookahead to the end or next path segment. + route += strict && endsWithSlash ? '' : '(?=\\/|$)' + } + + return new RegExp('^' + route, flags(options)) + } + + /** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(string|RegExp|Array)} path + * @param {(Array|Object)=} keys + * @param {Object=} options + * @return {!RegExp} + */ + function pathToRegexp (path, keys, options) { + keys = keys || [] + + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys) + keys = [] + } else if (!options) { + options = {} + } + + if (path instanceof RegExp) { + return regexpToRegexp(path, /** @type {!Array} */ (keys)) + } + + if (isarray(path)) { + return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options) + } + + return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options) + } + + index.parse = parse_1; + index.compile = compile_1; + index.tokensToFunction = tokensToFunction_1; + index.tokensToRegExp = tokensToRegExp_1; + + /* */ + + function createRouteMap (routes) { + var pathMap = Object.create(null) + var nameMap = Object.create(null) + + routes.forEach(function (route) { + addRouteRecord(pathMap, nameMap, route) + }) + + return { + pathMap: pathMap, + nameMap: nameMap + } + } + + function addRouteRecord ( + pathMap, + nameMap, + route, + parent, + matchAs + ) { + var path = route.path; + var name = route.name; + assert(path != null, "\"path\" is required in a route configuration.") + + var record = { + path: normalizePath(path, parent), + components: route.components || { default: route.component }, + instances: {}, + name: name, + parent: parent, + matchAs: matchAs, + redirect: route.redirect, + beforeEnter: route.beforeEnter, + meta: route.meta || {} + } + + if (route.children) { + // Warn if route is named and has a default child route. + // If users navigate to this route by name, the default child will + // not be rendered (GH Issue #629) + if (false) {} + route.children.forEach(function (child) { + addRouteRecord(pathMap, nameMap, child, record) + }) + } + + if (route.alias) { + if (Array.isArray(route.alias)) { + route.alias.forEach(function (alias) { + addRouteRecord(pathMap, nameMap, { path: alias }, parent, record.path) + }) + } else { + addRouteRecord(pathMap, nameMap, { path: route.alias }, parent, record.path) + } + } + + pathMap[record.path] = record + if (name) { nameMap[name] = record } + } + + function normalizePath (path, parent) { + path = path.replace(/\/$/, '') + if (path[0] === '/') { return path } + if (parent == null) { return path } + return cleanPath(((parent.path) + "/" + path)) + } + + /* */ + + var regexpCache = Object.create(null) + + var regexpCompileCache = Object.create(null) + + function createMatcher (routes) { + var ref = createRouteMap(routes); + var pathMap = ref.pathMap; + var nameMap = ref.nameMap; + + function match ( + raw, + currentRoute, + redirectedFrom + ) { + var location = normalizeLocation(raw, currentRoute) + var name = location.name; + + if (name) { + var record = nameMap[name] + if (record) { + location.path = fillParams(record.path, location.params, ("named route \"" + name + "\"")) + return _createRoute(record, location, redirectedFrom) + } + } else if (location.path) { + location.params = {} + for (var path in pathMap) { + if (matchRoute(path, location.params, location.path)) { + return _createRoute(pathMap[path], location, redirectedFrom) + } + } + } + // no match + return _createRoute(null, location) + } + + function redirect ( + record, + location + ) { + var originalRedirect = record.redirect + var redirect = typeof originalRedirect === 'function' + ? originalRedirect(createRoute(record, location)) + : originalRedirect + + if (typeof redirect === 'string') { + redirect = { path: redirect } + } + + if (!redirect || typeof redirect !== 'object') { + warn(false, ("invalid redirect option: " + (JSON.stringify(redirect)))) + return _createRoute(null, location) + } + + var re = redirect + var name = re.name; + var path = re.path; + var query = location.query; + var hash = location.hash; + var params = location.params; + query = re.hasOwnProperty('query') ? re.query : query + hash = re.hasOwnProperty('hash') ? re.hash : hash + params = re.hasOwnProperty('params') ? re.params : params + + if (name) { + // resolved named direct + var targetRecord = nameMap[name] + assert(targetRecord, ("redirect failed: named route \"" + name + "\" not found.")) + return match({ + _normalized: true, + name: name, + query: query, + hash: hash, + params: params + }, undefined, location) + } else if (path) { + // 1. resolve relative redirect + var rawPath = resolveRecordPath(path, record) + // 2. resolve params + var resolvedPath = fillParams(rawPath, params, ("redirect route with path \"" + rawPath + "\"")) + // 3. rematch with existing query and hash + return match({ + _normalized: true, + path: resolvedPath, + query: query, + hash: hash + }, undefined, location) + } else { + warn(false, ("invalid redirect option: " + (JSON.stringify(redirect)))) + return _createRoute(null, location) + } + } + + function alias ( + record, + location, + matchAs + ) { + var aliasedPath = fillParams(matchAs, location.params, ("aliased route with path \"" + matchAs + "\"")) + var aliasedMatch = match({ + _normalized: true, + path: aliasedPath + }) + if (aliasedMatch) { + var matched = aliasedMatch.matched + var aliasedRecord = matched[matched.length - 1] + location.params = aliasedMatch.params + return _createRoute(aliasedRecord, location) + } + return _createRoute(null, location) + } + + function _createRoute ( + record, + location, + redirectedFrom + ) { + if (record && record.redirect) { + return redirect(record, redirectedFrom || location) + } + if (record && record.matchAs) { + return alias(record, location, record.matchAs) + } + return createRoute(record, location, redirectedFrom) + } + + return match + } + + function matchRoute ( + path, + params, + pathname + ) { + var keys, regexp + var hit = regexpCache[path] + if (hit) { + keys = hit.keys + regexp = hit.regexp + } else { + keys = [] + regexp = index(path, keys) + regexpCache[path] = { keys: keys, regexp: regexp } + } + var m = pathname.match(regexp) + + if (!m) { + return false + } else if (!params) { + return true + } + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1] + var val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i] + if (key) { params[key.name] = val } + } + + return true + } + + function fillParams ( + path, + params, + routeMsg + ) { + try { + var filler = + regexpCompileCache[path] || + (regexpCompileCache[path] = index.compile(path)) + return filler(params || {}, { pretty: true }) + } catch (e) { + assert(false, ("missing param for " + routeMsg + ": " + (e.message))) + return '' + } + } + + function resolveRecordPath (path, record) { + return resolvePath(path, record.parent ? record.parent.path : '/', true) + } + + /* */ + + var inBrowser = typeof window !== 'undefined' + + var supportsHistory = inBrowser && (function () { + var ua = window.navigator.userAgent + + if ( + (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && + ua.indexOf('Mobile Safari') !== -1 && + ua.indexOf('Chrome') === -1 && + ua.indexOf('Windows Phone') === -1 + ) { + return false + } + + return window.history && 'pushState' in window.history + })() + + /* */ + + function runQueue (queue, fn, cb) { + var step = function (index) { + if (index >= queue.length) { + cb() + } else { + if (queue[index]) { + fn(queue[index], function () { + step(index + 1) + }) + } else { + step(index + 1) + } + } + } + step(0) + } + + /* */ + + + var History = function History (router, base) { + this.router = router + this.base = normalizeBase(base) + // start with a route object that stands for "nowhere" + this.current = START + this.pending = null + }; + + History.prototype.listen = function listen (cb) { + this.cb = cb + }; + + History.prototype.transitionTo = function transitionTo (location, cb) { + var this$1 = this; + + var route = this.router.match(location, this.current) + this.confirmTransition(route, function () { + this$1.updateRoute(route) + cb && cb(route) + this$1.ensureURL() + }) + }; + + History.prototype.confirmTransition = function confirmTransition (route, cb) { + var this$1 = this; + + var current = this.current + if (isSameRoute(route, current)) { + this.ensureURL() + return + } + + var ref = resolveQueue(this.current.matched, route.matched); + var deactivated = ref.deactivated; + var activated = ref.activated; + + var queue = [].concat( + // in-component leave guards + extractLeaveGuards(deactivated), + // global before hooks + this.router.beforeHooks, + // enter guards + activated.map(function (m) { return m.beforeEnter; }), + // async components + resolveAsyncComponents(activated) + ) + + this.pending = route + var iterator = function (hook, next) { + if (this$1.pending !== route) { return } + hook(route, current, function (to) { + if (to === false) { + // next(false) -> abort navigation, ensure current URL + this$1.ensureURL() + } else if (typeof to === 'string' || typeof to === 'object') { + // next('/') or next({ path: '/' }) -> redirect + this$1.push(to) + } else { + // confirm transition and pass on the value + next(to) + } + }) + } + + runQueue(queue, iterator, function () { + var postEnterCbs = [] + // wait until async components are resolved before + // extracting in-component enter guards + runQueue(extractEnterGuards(activated, postEnterCbs), iterator, function () { + if (this$1.pending === route) { + this$1.pending = null + cb(route) + this$1.router.app.$nextTick(function () { + postEnterCbs.forEach(function (cb) { return cb(); }) + }) + } + }) + }) + }; + + History.prototype.updateRoute = function updateRoute (route) { + var prev = this.current + this.current = route + this.cb && this.cb(route) + this.router.afterHooks.forEach(function (hook) { + hook && hook(route, prev) + }) + }; + + function normalizeBase (base) { + if (!base) { + if (inBrowser) { + // respect tag + var baseEl = document.querySelector('base') + base = baseEl ? baseEl.getAttribute('href') : '/' + } else { + base = '/' + } + } + // make sure there's the starting slash + if (base.charAt(0) !== '/') { + base = '/' + base + } + // remove trailing slash + return base.replace(/\/$/, '') + } + + function resolveQueue ( + current, + next + ) { + var i + var max = Math.max(current.length, next.length) + for (i = 0; i < max; i++) { + if (current[i] !== next[i]) { + break + } + } + return { + activated: next.slice(i), + deactivated: current.slice(i) + } + } + + function extractLeaveGuards (matched) { + return flatMapComponents(matched, function (def, instance) { + var guard = def && def.beforeRouteLeave + if (guard) { + return function routeLeaveGuard () { + return guard.apply(instance, arguments) + } + } + }).reverse() + } + + function extractEnterGuards (matched, cbs) { + return flatMapComponents(matched, function (def, _, match, key) { + var guard = def && def.beforeRouteEnter + if (guard) { + return function routeEnterGuard (to, from, next) { + return guard(to, from, function (cb) { + next(cb) + if (typeof cb === 'function') { + cbs.push(function () { + cb(match.instances[key]) + }) + } + }) + } + } + }) + } + + function resolveAsyncComponents (matched) { + return flatMapComponents(matched, function (def, _, match, key) { + // if it's a function and doesn't have Vue options attached, + // assume it's an async component resolve function. + // we are not using Vue's default async resolving mechanism because + // we want to halt the navigation until the incoming component has been + // resolved. + if (typeof def === 'function' && !def.options) { + return function (to, from, next) { + var resolve = function (resolvedDef) { + match.components[key] = resolvedDef + next() + } + + var reject = function (reason) { + warn(false, ("Failed to resolve async component " + key + ": " + reason)) + next(false) + } + + var res = def(resolve, reject) + if (res && typeof res.then === 'function') { + res.then(resolve, reject) + } + } + } + }) + } + + function flatMapComponents ( + matched, + fn + ) { + return Array.prototype.concat.apply([], matched.map(function (m) { + return Object.keys(m.components).map(function (key) { return fn( + m.components[key], + m.instances[key], + m, key + ); }) + })) + } + + /* */ + + function saveScrollPosition (key) { + if (!key) { return } + window.sessionStorage.setItem(key, JSON.stringify({ + x: window.pageXOffset, + y: window.pageYOffset + })) + } + + function getScrollPosition (key) { + if (!key) { return } + return JSON.parse(window.sessionStorage.getItem(key)) + } + + function getElementPosition (el) { + var docRect = document.documentElement.getBoundingClientRect() + var elRect = el.getBoundingClientRect() + return { + x: elRect.left - docRect.left, + y: elRect.top - docRect.top + } + } + + function isValidPosition (obj) { + return isNumber(obj.x) || isNumber(obj.y) + } + + function normalizePosition (obj) { + return { + x: isNumber(obj.x) ? obj.x : window.pageXOffset, + y: isNumber(obj.y) ? obj.y : window.pageYOffset + } + } + + function isNumber (v) { + return typeof v === 'number' + } + + /* */ + + + var genKey = function () { return String(Date.now()); } + var _key = genKey() + + var HTML5History = (function (History) { + function HTML5History (router, base) { + var this$1 = this; + + History.call(this, router, base) + + this.transitionTo(getLocation(this.base)) + + var expectScroll = router.options.scrollBehavior + window.addEventListener('popstate', function (e) { + _key = e.state && e.state.key + var current = this$1.current + this$1.transitionTo(getLocation(this$1.base), function (next) { + if (expectScroll) { + this$1.handleScroll(next, current, true) + } + }) + }) + + if (expectScroll) { + window.addEventListener('scroll', function () { + saveScrollPosition(_key) + }) + } + } + + if ( History ) HTML5History.__proto__ = History; + HTML5History.prototype = Object.create( History && History.prototype ); + HTML5History.prototype.constructor = HTML5History; + + HTML5History.prototype.go = function go (n) { + window.history.go(n) + }; + + HTML5History.prototype.push = function push (location) { + var this$1 = this; + + var current = this.current + this.transitionTo(location, function (route) { + pushState(cleanPath(this$1.base + route.fullPath)) + this$1.handleScroll(route, current, false) + }) + }; + + HTML5History.prototype.replace = function replace (location) { + var this$1 = this; + + var current = this.current + this.transitionTo(location, function (route) { + replaceState(cleanPath(this$1.base + route.fullPath)) + this$1.handleScroll(route, current, false) + }) + }; + + HTML5History.prototype.ensureURL = function ensureURL () { + if (getLocation(this.base) !== this.current.fullPath) { + replaceState(cleanPath(this.base + this.current.fullPath)) + } + }; + + HTML5History.prototype.handleScroll = function handleScroll (to, from, isPop) { + var router = this.router + if (!router.app) { + return + } + + var behavior = router.options.scrollBehavior + if (!behavior) { + return + } + assert(typeof behavior === 'function', "scrollBehavior must be a function") + + // wait until re-render finishes before scrolling + router.app.$nextTick(function () { + var position = getScrollPosition(_key) + var shouldScroll = behavior(to, from, isPop ? position : null) + if (!shouldScroll) { + return + } + var isObject = typeof shouldScroll === 'object' + if (isObject && typeof shouldScroll.selector === 'string') { + var el = document.querySelector(shouldScroll.selector) + if (el) { + position = getElementPosition(el) + } else if (isValidPosition(shouldScroll)) { + position = normalizePosition(shouldScroll) + } + } else if (isObject && isValidPosition(shouldScroll)) { + position = normalizePosition(shouldScroll) + } + + if (position) { + window.scrollTo(position.x, position.y) + } + }) + }; + + return HTML5History; + }(History)); + + function getLocation (base) { + var path = window.location.pathname + if (base && path.indexOf(base) === 0) { + path = path.slice(base.length) + } + return (path || '/') + window.location.search + window.location.hash + } + + function pushState (url, replace) { + // try...catch the pushState call to get around Safari + // DOM Exception 18 where it limits to 100 pushState calls + var history = window.history + try { + if (replace) { + history.replaceState({ key: _key }, '', url) + } else { + _key = genKey() + history.pushState({ key: _key }, '', url) + } + saveScrollPosition(_key) + } catch (e) { + window.location[replace ? 'assign' : 'replace'](url) + } + } + + function replaceState (url) { + pushState(url, true) + } + + /* */ + + + var HashHistory = (function (History) { + function HashHistory (router, base, fallback) { + var this$1 = this; + + History.call(this, router, base) + + // check history fallback deeplinking + if (fallback && this.checkFallback()) { + return + } + + ensureSlash() + this.transitionTo(getHash()) + + window.addEventListener('hashchange', function () { + this$1.onHashChange() + }) + } + + if ( History ) HashHistory.__proto__ = History; + HashHistory.prototype = Object.create( History && History.prototype ); + HashHistory.prototype.constructor = HashHistory; + + HashHistory.prototype.checkFallback = function checkFallback () { + var location = getLocation(this.base) + if (!/^\/#/.test(location)) { + window.location.replace( + cleanPath(this.base + '/#' + location) + ) + return true + } + }; + + HashHistory.prototype.onHashChange = function onHashChange () { + if (!ensureSlash()) { + return + } + this.transitionTo(getHash(), function (route) { + replaceHash(route.fullPath) + }) + }; + + HashHistory.prototype.push = function push (location) { + History.prototype.transitionTo.call(this, location, function (route) { + pushHash(route.fullPath) + }) + }; + + HashHistory.prototype.replace = function replace (location) { + History.prototype.transitionTo.call(this, location, function (route) { + replaceHash(route.fullPath) + }) + }; + + HashHistory.prototype.go = function go (n) { + window.history.go(n) + }; + + HashHistory.prototype.ensureURL = function ensureURL () { + if (getHash() !== this.current.fullPath) { + replaceHash(this.current.fullPath) + } + }; + + return HashHistory; + }(History)); + + function ensureSlash () { + var path = getHash() + if (path.charAt(0) === '/') { + return true + } + replaceHash('/' + path) + return false + } + + function getHash () { + // We can't use window.location.hash here because it's not + // consistent across browsers - Firefox will pre-decode it! + var href = window.location.href + var index = href.indexOf('#') + return index === -1 ? '' : href.slice(index + 1) + } + + function pushHash (path) { + window.location.hash = path + } + + function replaceHash (path) { + var i = window.location.href.indexOf('#') + window.location.replace( + window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path + ) + } + + /* */ + + + var AbstractHistory = (function (History) { + function AbstractHistory (router) { + History.call(this, router) + this.stack = [] + this.index = 0 + } + + if ( History ) AbstractHistory.__proto__ = History; + AbstractHistory.prototype = Object.create( History && History.prototype ); + AbstractHistory.prototype.constructor = AbstractHistory; + + AbstractHistory.prototype.push = function push (location) { + var this$1 = this; + + History.prototype.transitionTo.call(this, location, function (route) { + this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route) + this$1.index++ + }) + }; + + AbstractHistory.prototype.replace = function replace (location) { + var this$1 = this; + + History.prototype.transitionTo.call(this, location, function (route) { + this$1.stack = this$1.stack.slice(0, this$1.index).concat(route) + }) + }; + + AbstractHistory.prototype.go = function go (n) { + var this$1 = this; + + var targetIndex = this.index + n + if (targetIndex < 0 || targetIndex >= this.stack.length) { + return + } + var location = this.stack[targetIndex] + this.confirmTransition(location, function () { + this$1.index = targetIndex + this$1.updateRoute(location) + }) + }; + + AbstractHistory.prototype.ensureURL = function ensureURL () { + // noop + }; + + return AbstractHistory; + }(History)); + + /* */ + + var VueRouter = function VueRouter (options) { + if ( options === void 0 ) options = {}; + + this.app = null + this.options = options + this.beforeHooks = [] + this.afterHooks = [] + this.match = createMatcher(options.routes || []) + + var mode = options.mode || 'hash' + this.fallback = mode === 'history' && !supportsHistory + if (this.fallback) { + mode = 'hash' + } + if (!inBrowser) { + mode = 'abstract' + } + this.mode = mode + }; + + var prototypeAccessors = { currentRoute: {} }; + + prototypeAccessors.currentRoute.get = function () { + return this.history && this.history.current + }; + + VueRouter.prototype.init = function init (app /* Vue component instance */) { + var this$1 = this; + + assert( + install.installed, + "not installed. Make sure to call `Vue.use(VueRouter)` " + + "before creating root instance." + ) + + this.app = app + + var ref = this; + var mode = ref.mode; + var options = ref.options; + var fallback = ref.fallback; + switch (mode) { + case 'history': + this.history = new HTML5History(this, options.base) + break + case 'hash': + this.history = new HashHistory(this, options.base, fallback) + break + case 'abstract': + this.history = new AbstractHistory(this) + break + default: + assert(false, ("invalid mode: " + mode)) + } + + this.history.listen(function (route) { + this$1.app._route = route + }) + }; + + VueRouter.prototype.beforeEach = function beforeEach (fn) { + this.beforeHooks.push(fn) + }; + + VueRouter.prototype.afterEach = function afterEach (fn) { + this.afterHooks.push(fn) + }; + + VueRouter.prototype.push = function push (location) { + this.history.push(location) + }; + + VueRouter.prototype.replace = function replace (location) { + this.history.replace(location) + }; + + VueRouter.prototype.go = function go (n) { + this.history.go(n) + }; + + VueRouter.prototype.back = function back () { + this.go(-1) + }; + + VueRouter.prototype.forward = function forward () { + this.go(1) + }; + + VueRouter.prototype.getMatchedComponents = function getMatchedComponents () { + if (!this.currentRoute) { + return [] + } + return [].concat.apply([], this.currentRoute.matched.map(function (m) { + return Object.keys(m.components).map(function (key) { + return m.components[key] + }) + })) + }; + + Object.defineProperties( VueRouter.prototype, prototypeAccessors ); + + VueRouter.install = install + + if (inBrowser && window.Vue) { + window.Vue.use(VueRouter) + } + + return VueRouter; + + }))); + +/***/ }, +/* 90 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _vue = __webpack_require__(39); + + var _vue2 = _interopRequireDefault(_vue); + + var _vueResource = __webpack_require__(45); + + var _vueResource2 = _interopRequireDefault(_vueResource); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + _vue2.default.use(_vueResource2.default); + + _vue2.default.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content'); + + var _document$body$datase = document.body.dataset; + var url = _document$body$datase.url; + var uri = _document$body$datase.uri; + var auth = _document$body$datase.auth; + var scoutDriver = _document$body$datase.scoutDriver; + exports.default = { + uri: uri, + url: url, + auth: auth, + scoutDriver: scoutDriver, + poster: url + '/assets/poster', + posterTMDB: 'http://image.tmdb.org/t/p/w185', + api: url + '/api' + }; + +/***/ }, +/* 91 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(92) + + /* template */ + var __vue_template__ = __webpack_require__(96) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-5", __vue_options__) + } else { + hotAPI.reload("data-v-5", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Content.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 92 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _extends2 = __webpack_require__(1); + + var _extends3 = _interopRequireDefault(_extends2); + + var _Item = __webpack_require__(93); + + var _Item2 = _interopRequireDefault(_Item); + + var _vuex = __webpack_require__(40); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = { + created: function created() { + this.fetchData(); + }, + + + computed: (0, _extends3.default)({}, (0, _vuex.mapState)({ + loading: function loading(state) { + return state.loading; + }, + items: function items(state) { + return state.items; + }, + userFilter: function userFilter(state) { + return state.userFilter; + }, + clickedMoreLoading: function clickedMoreLoading(state) { + return state.clickedMoreLoading; + }, + paginator: function paginator(state) { + return state.paginator; + } + })), + + methods: (0, _extends3.default)({}, (0, _vuex.mapActions)(['loadItems', 'loadMoreItems', 'setSearchTitle']), { + fetchData: function fetchData() { + this.loadItems(this.userFilter); + this.setSearchTitle(''); + }, + loadMore: function loadMore() { + this.loadMoreItems(this.paginator); + } + }), + + components: { + Item: _Item2.default + }, + + watch: { + '$route': 'fetchData' + } + }; + +/***/ }, +/* 93 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(94) + + /* template */ + var __vue_template__ = __webpack_require__(95) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-8", __vue_options__) + } else { + hotAPI.reload("data-v-8", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Item.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 94 */ +/***/ function(module, exports) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.default = { + props: ['item'], + + data: function data() { + return { + localItem: this.item, + saveTimeout: null, + auth: config.auth, + prevRating: null, + rated: false + }; + }, + + + computed: { + title: function title() { + return this.localItem.alternative_title ? this.localItem.alternative_title : this.localItem.title; + }, + poster: function poster() { + if (this.localItem.rating) { + return config.poster + this.localItem.poster; + } + + return config.posterTMDB + this.localItem.poster; + }, + released: function released() { + var released = new Date(this.localItem.released * 1000); + + return released.getFullYear(); + } + }, + + methods: { + changeRating: function changeRating() { + var _this = this; + + if (this.auth) { + clearTimeout(this.saveTimeout); + + this.prevRating = this.localItem.rating; + this.localItem.rating = this.prevRating == 3 ? 1 : +this.prevRating + 1; + + this.saveTimeout = setTimeout(function () { + _this.saveNewRating(); + }, 500); + } + }, + saveNewRating: function saveNewRating() { + var _this2 = this; + + this.$http.patch(config.api + '/change-rating/' + this.localItem.id, { rating: this.localItem.rating }).catch(function (error) { + _this2.localItem.rating = _this2.prevRating; + alert('Error in saveNewRating()'); + }); + }, + addNewItem: function addNewItem() { + var _this3 = this; + + if (this.auth) { + this.rated = true; + + this.$http.post(config.api + '/add', { item: this.localItem }).then(function (value) { + _this3.localItem = value.data; + }, function (error) { + if (error.status == 409) { + alert(_this3.title + ' already exists!'); + } + }); + } + }, + removeItem: function removeItem() { + var _this4 = this; + + if (this.auth) { + var confirm = window.confirm('Are you sure?'); + + if (confirm) { + this.$http.delete(config.api + '/remove/' + this.localItem.id).then(function (value) { + _this4.localItem.rating = null; + }, function (error) { + alert('Error in removeItem()'); + }); + } + } + } + } + }; + +/***/ }, +/* 95 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('transition', { + attrs: { + "mode": "out-in", + "name": "fade" + } + }, [_h('div', { + staticClass: "item-wrap" + }, [_h('div', { + staticClass: "item-image-wrap" + }, [(localItem.rating) ? _h('span', { + class: 'item-rating rating-' + localItem.rating, + on: { + "click": function($event) { + changeRating() + } + } + }, [_m(0)]) : _e(), " ", (!localItem.rating) ? _h('span', { + staticClass: "item-rating item-new", + on: { + "click": function($event) { + addNewItem() + } + } + }, [(rated) ? _h('span', { + staticClass: "loader smallsize-loader" + }, [_m(1)]) : _e(), " ", (!rated) ? _h('i', { + staticClass: "icon-add" + }) : _e()]) : _e(), " ", (localItem.rating && auth) ? _h('span', { + staticClass: "remove-item", + on: { + "click": function($event) { + removeItem() + } + } + }, [_m(2)]) : _e(), " ", (localItem.poster) ? _h('img', { + staticClass: "item-image", + attrs: { + "src": poster, + "width": "185", + "height": "278" + } + }) : _e(), " ", (!localItem.poster) ? _h('span', { + staticClass: "no-image" + }) : _e()]), " ", _h('div', { + staticClass: "item-content" + }, [_h('span', { + staticClass: "item-year" + }, [_s(released)]), " ", _h('a', { + staticClass: "item-title", + attrs: { + "href": 'https://www.youtube.com/results?search_query=' + title + ' Trailer', + "target": "_blank", + "title": title + } + }, [_s(title)])])])]) + }},staticRenderFns: [function (){with(this) { + return _h('i', { + staticClass: "icon-rating" + }) + }},function (){with(this) { + return _h('i') + }},function (){with(this) { + return _h('i', { + staticClass: "icon-remove" + }) + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-8", module.exports) + } + } + +/***/ }, +/* 96 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('main', [(!loading) ? _h('div', { + staticClass: "wrap-content" + }, [_l((items), function(item, index) { + return _h('Item', { + key: index, + attrs: { + "item": item + } + }) + }), " ", (!items.length) ? _h('span', { + staticClass: "nothing-found" + }, ["No Movies Found"]) : _e(), " ", _h('div', { + staticClass: "load-more-wrap" + }, [(!clickedMoreLoading && paginator) ? _h('span', { + staticClass: "load-more", + on: { + "click": function($event) { + loadMore() + } + } + }, ["LOAD MORE"]) : _e(), " ", (clickedMoreLoading) ? _h('span', { + staticClass: "loader" + }, [_m(0)]) : _e()])]) : _e(), " ", (loading) ? _h('span', { + staticClass: "loader fullsize-loader" + }, [_m(1)]) : _e()]) + }},staticRenderFns: [function (){with(this) { + return _h('i') + }},function (){with(this) { + return _h('i') + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-5", module.exports) + } + } + +/***/ }, +/* 97 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(98) + + /* template */ + var __vue_template__ = __webpack_require__(120) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-6", __vue_options__) + } else { + hotAPI.reload("data-v-6", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] SearchContent.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 98 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _regenerator = __webpack_require__(99); + + var _regenerator2 = _interopRequireDefault(_regenerator); + + var _asyncToGenerator2 = __webpack_require__(103); + + var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); + + var _extends2 = __webpack_require__(1); + + var _extends3 = _interopRequireDefault(_extends2); + + var _Item = __webpack_require__(93); + + var _Item2 = _interopRequireDefault(_Item); + + var _helper = __webpack_require__(79); + + var _helper2 = _interopRequireDefault(_helper); + + var _vuex = __webpack_require__(40); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = { + mixins: [_helper2.default], + + created: function created() { + this.initSearch(); + }, + data: function data() { + return { + floxItems: [], + tmdbItems: [] + }; + }, + + + computed: (0, _extends3.default)({}, (0, _vuex.mapState)({ + searchTitle: function searchTitle(state) { + return state.searchTitle; + }, + loading: function loading(state) { + return state.loading; + } + })), + + methods: { + initSearch: function initSearch() { + var _this = this; + + this.$store.commit('SET_SEARCH_TITLE', this.$route.query.q); + this.$store.commit('SET_LOADING', true); + this.searchFlox(); + this.searchTMDB().then(function () { + setTimeout(function () { + _this.$store.commit('SET_LOADING', false); + }, 500); + }); + }, + searchFlox: function searchFlox() { + var _this2 = this; + + this.$http.get(config.api + '/search-items?q=' + this.searchTitle).then(function (value) { + _this2.floxItems = value.data; + }); + }, + searchTMDB: function searchTMDB() { + var _this3 = this; + + return (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() { + return _regenerator2.default.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + if (!config.auth) { + _context.next = 3; + break; + } + + _context.next = 3; + return _this3.$http.get(config.api + '/search-tmdb?q=' + _this3.searchTitle).then(function (value) { + var floxItems = _this3.floxItems.map(function (item) { + return item.tmdb_id; + }); + _this3.tmdbItems = value.data.filter(function (item) { + return !floxItems.includes(item.tmdb_id); + }); + }).catch(function (error) { + alert('Error in searchTMDB(): ' + error); + }); + + case 3: + case 'end': + return _context.stop(); + } + } + }, _callee, _this3); + }))(); + } + }, + + components: { + Item: _Item2.default + }, + + watch: { + $route: function $route() { + this.scrollToTop(); + this.initSearch(); + } + } + }; + +/***/ }, +/* 99 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(100); + + +/***/ }, +/* 100 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {// This method of obtaining a reference to the global object needs to be + // kept identical to the way it is obtained in runtime.js + var g = + typeof global === "object" ? global : + typeof window === "object" ? window : + typeof self === "object" ? self : this; + + // Use `getOwnPropertyNames` because not all browsers support calling + // `hasOwnProperty` on the global `self` object in a worker. See #183. + var hadRuntime = g.regeneratorRuntime && + Object.getOwnPropertyNames(g).indexOf("regeneratorRuntime") >= 0; + + // Save the old regeneratorRuntime in case it needs to be restored later. + var oldRuntime = hadRuntime && g.regeneratorRuntime; + + // Force reevalutation of runtime.js. + g.regeneratorRuntime = undefined; + + module.exports = __webpack_require__(101); + + if (hadRuntime) { + // Restore the original runtime. + g.regeneratorRuntime = oldRuntime; + } else { + // Remove the global property added by runtime.js. + try { + delete g.regeneratorRuntime; + } catch(e) { + g.regeneratorRuntime = undefined; + } + } + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) + +/***/ }, +/* 101 */ +/***/ function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global, process) {/** + * Copyright (c) 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * https://raw.github.com/facebook/regenerator/master/LICENSE file. An + * additional grant of patent rights can be found in the PATENTS file in + * the same directory. + */ + + !(function(global) { + "use strict"; + + var hasOwn = Object.prototype.hasOwnProperty; + var undefined; // More compressible than void 0. + var $Symbol = typeof Symbol === "function" ? Symbol : {}; + var iteratorSymbol = $Symbol.iterator || "@@iterator"; + var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; + + var inModule = typeof module === "object"; + var runtime = global.regeneratorRuntime; + if (runtime) { + if (inModule) { + // If regeneratorRuntime is defined globally and we're in a module, + // make the exports object identical to regeneratorRuntime. + module.exports = runtime; + } + // Don't bother evaluating the rest of this file if the runtime was + // already defined globally. + return; + } + + // Define the runtime globally (as expected by generated code) as either + // module.exports (if we're in a module) or a new, empty object. + runtime = global.regeneratorRuntime = inModule ? module.exports : {}; + + function wrap(innerFn, outerFn, self, tryLocsList) { + // If outerFn provided, then outerFn.prototype instanceof Generator. + var generator = Object.create((outerFn || Generator).prototype); + var context = new Context(tryLocsList || []); + + // The ._invoke method unifies the implementations of the .next, + // .throw, and .return methods. + generator._invoke = makeInvokeMethod(innerFn, self, context); + + return generator; + } + runtime.wrap = wrap; + + // Try/catch helper to minimize deoptimizations. Returns a completion + // record like context.tryEntries[i].completion. This interface could + // have been (and was previously) designed to take a closure to be + // invoked without arguments, but in all the cases we care about we + // already have an existing method we want to call, so there's no need + // to create a new function object. We can even get away with assuming + // the method takes exactly one argument, since that happens to be true + // in every case, so we don't have to touch the arguments object. The + // only additional allocation required is the completion record, which + // has a stable shape and so hopefully should be cheap to allocate. + function tryCatch(fn, obj, arg) { + try { + return { type: "normal", arg: fn.call(obj, arg) }; + } catch (err) { + return { type: "throw", arg: err }; + } + } + + var GenStateSuspendedStart = "suspendedStart"; + var GenStateSuspendedYield = "suspendedYield"; + var GenStateExecuting = "executing"; + var GenStateCompleted = "completed"; + + // Returning this object from the innerFn has the same effect as + // breaking out of the dispatch switch statement. + var ContinueSentinel = {}; + + // Dummy constructor functions that we use as the .constructor and + // .constructor.prototype properties for functions that return Generator + // objects. For full spec compliance, you may wish to configure your + // minifier not to mangle the names of these two functions. + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + + var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype; + GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; + GeneratorFunctionPrototype.constructor = GeneratorFunction; + GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction"; + + // Helper for defining the .next, .throw, and .return methods of the + // Iterator interface in terms of a single ._invoke method. + function defineIteratorMethods(prototype) { + ["next", "throw", "return"].forEach(function(method) { + prototype[method] = function(arg) { + return this._invoke(method, arg); + }; + }); + } + + runtime.isGeneratorFunction = function(genFun) { + var ctor = typeof genFun === "function" && genFun.constructor; + return ctor + ? ctor === GeneratorFunction || + // For the native GeneratorFunction constructor, the best we can + // do is to check its .name property. + (ctor.displayName || ctor.name) === "GeneratorFunction" + : false; + }; + + runtime.mark = function(genFun) { + if (Object.setPrototypeOf) { + Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); + } else { + genFun.__proto__ = GeneratorFunctionPrototype; + if (!(toStringTagSymbol in genFun)) { + genFun[toStringTagSymbol] = "GeneratorFunction"; + } + } + genFun.prototype = Object.create(Gp); + return genFun; + }; + + // Within the body of any async function, `await x` is transformed to + // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test + // `value instanceof AwaitArgument` to determine if the yielded value is + // meant to be awaited. Some may consider the name of this method too + // cutesy, but they are curmudgeons. + runtime.awrap = function(arg) { + return new AwaitArgument(arg); + }; + + function AwaitArgument(arg) { + this.arg = arg; + } + + function AsyncIterator(generator) { + function invoke(method, arg, resolve, reject) { + var record = tryCatch(generator[method], generator, arg); + if (record.type === "throw") { + reject(record.arg); + } else { + var result = record.arg; + var value = result.value; + if (value instanceof AwaitArgument) { + return Promise.resolve(value.arg).then(function(value) { + invoke("next", value, resolve, reject); + }, function(err) { + invoke("throw", err, resolve, reject); + }); + } + + return Promise.resolve(value).then(function(unwrapped) { + // When a yielded Promise is resolved, its final value becomes + // the .value of the Promise<{value,done}> result for the + // current iteration. If the Promise is rejected, however, the + // result for this iteration will be rejected with the same + // reason. Note that rejections of yielded Promises are not + // thrown back into the generator function, as is the case + // when an awaited Promise is rejected. This difference in + // behavior between yield and await is important, because it + // allows the consumer to decide what to do with the yielded + // rejection (swallow it and continue, manually .throw it back + // into the generator, abandon iteration, whatever). With + // await, by contrast, there is no opportunity to examine the + // rejection reason outside the generator function, so the + // only option is to throw it from the await expression, and + // let the generator function handle the exception. + result.value = unwrapped; + resolve(result); + }, reject); + } + } + + if (typeof process === "object" && process.domain) { + invoke = process.domain.bind(invoke); + } + + var previousPromise; + + function enqueue(method, arg) { + function callInvokeWithMethodAndArg() { + return new Promise(function(resolve, reject) { + invoke(method, arg, resolve, reject); + }); + } + + return previousPromise = + // If enqueue has been called before, then we want to wait until + // all previous Promises have been resolved before calling invoke, + // so that results are always delivered in the correct order. If + // enqueue has not been called before, then it is important to + // call invoke immediately, without waiting on a callback to fire, + // so that the async generator function has the opportunity to do + // any necessary setup in a predictable way. This predictability + // is why the Promise constructor synchronously invokes its + // executor callback, and why async functions synchronously + // execute code before the first await. Since we implement simple + // async functions in terms of async generators, it is especially + // important to get this right, even though it requires care. + previousPromise ? previousPromise.then( + callInvokeWithMethodAndArg, + // Avoid propagating failures to Promises returned by later + // invocations of the iterator. + callInvokeWithMethodAndArg + ) : callInvokeWithMethodAndArg(); + } + + // Define the unified helper method that is used to implement .next, + // .throw, and .return (see defineIteratorMethods). + this._invoke = enqueue; + } + + defineIteratorMethods(AsyncIterator.prototype); + + // Note that simple async functions are implemented on top of + // AsyncIterator objects; they just return a Promise for the value of + // the final result produced by the iterator. + runtime.async = function(innerFn, outerFn, self, tryLocsList) { + var iter = new AsyncIterator( + wrap(innerFn, outerFn, self, tryLocsList) + ); + + return runtime.isGeneratorFunction(outerFn) + ? iter // If outerFn is a generator, return the full iterator. + : iter.next().then(function(result) { + return result.done ? result.value : iter.next(); + }); + }; + + function makeInvokeMethod(innerFn, self, context) { + var state = GenStateSuspendedStart; + + return function invoke(method, arg) { + if (state === GenStateExecuting) { + throw new Error("Generator is already running"); + } + + if (state === GenStateCompleted) { + if (method === "throw") { + throw arg; + } + + // Be forgiving, per 25.3.3.3.3 of the spec: + // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume + return doneResult(); + } + + while (true) { + var delegate = context.delegate; + if (delegate) { + if (method === "return" || + (method === "throw" && delegate.iterator[method] === undefined)) { + // A return or throw (when the delegate iterator has no throw + // method) always terminates the yield* loop. + context.delegate = null; + + // If the delegate iterator has a return method, give it a + // chance to clean up. + var returnMethod = delegate.iterator["return"]; + if (returnMethod) { + var record = tryCatch(returnMethod, delegate.iterator, arg); + if (record.type === "throw") { + // If the return method threw an exception, let that + // exception prevail over the original return or throw. + method = "throw"; + arg = record.arg; + continue; + } + } + + if (method === "return") { + // Continue with the outer return, now that the delegate + // iterator has been terminated. + continue; + } + } + + var record = tryCatch( + delegate.iterator[method], + delegate.iterator, + arg + ); + + if (record.type === "throw") { + context.delegate = null; + + // Like returning generator.throw(uncaught), but without the + // overhead of an extra function call. + method = "throw"; + arg = record.arg; + continue; + } + + // Delegate generator ran and handled its own exceptions so + // regardless of what the method was, we continue as if it is + // "next" with an undefined arg. + method = "next"; + arg = undefined; + + var info = record.arg; + if (info.done) { + context[delegate.resultName] = info.value; + context.next = delegate.nextLoc; + } else { + state = GenStateSuspendedYield; + return info; + } + + context.delegate = null; + } + + if (method === "next") { + // Setting context._sent for legacy support of Babel's + // function.sent implementation. + context.sent = context._sent = arg; + + } else if (method === "throw") { + if (state === GenStateSuspendedStart) { + state = GenStateCompleted; + throw arg; + } + + if (context.dispatchException(arg)) { + // If the dispatched exception was caught by a catch block, + // then let that catch block handle the exception normally. + method = "next"; + arg = undefined; + } + + } else if (method === "return") { + context.abrupt("return", arg); + } + + state = GenStateExecuting; + + var record = tryCatch(innerFn, self, context); + if (record.type === "normal") { + // If an exception is thrown from innerFn, we leave state === + // GenStateExecuting and loop back for another invocation. + state = context.done + ? GenStateCompleted + : GenStateSuspendedYield; + + var info = { + value: record.arg, + done: context.done + }; + + if (record.arg === ContinueSentinel) { + if (context.delegate && method === "next") { + // Deliberately forget the last sent value so that we don't + // accidentally pass it on to the delegate. + arg = undefined; + } + } else { + return info; + } + + } else if (record.type === "throw") { + state = GenStateCompleted; + // Dispatch the exception by looping back around to the + // context.dispatchException(arg) call above. + method = "throw"; + arg = record.arg; + } + } + }; + } + + // Define Generator.prototype.{next,throw,return} in terms of the + // unified ._invoke helper method. + defineIteratorMethods(Gp); + + Gp[iteratorSymbol] = function() { + return this; + }; + + Gp[toStringTagSymbol] = "Generator"; + + Gp.toString = function() { + return "[object Generator]"; + }; + + function pushTryEntry(locs) { + var entry = { tryLoc: locs[0] }; + + if (1 in locs) { + entry.catchLoc = locs[1]; + } + + if (2 in locs) { + entry.finallyLoc = locs[2]; + entry.afterLoc = locs[3]; + } + + this.tryEntries.push(entry); + } + + function resetTryEntry(entry) { + var record = entry.completion || {}; + record.type = "normal"; + delete record.arg; + entry.completion = record; + } + + function Context(tryLocsList) { + // The root entry object (effectively a try statement without a catch + // or a finally block) gives us a place to store values thrown from + // locations where there is no enclosing try statement. + this.tryEntries = [{ tryLoc: "root" }]; + tryLocsList.forEach(pushTryEntry, this); + this.reset(true); + } + + runtime.keys = function(object) { + var keys = []; + for (var key in object) { + keys.push(key); + } + keys.reverse(); + + // Rather than returning an object with a next method, we keep + // things simple and return the next function itself. + return function next() { + while (keys.length) { + var key = keys.pop(); + if (key in object) { + next.value = key; + next.done = false; + return next; + } + } + + // To avoid creating an additional object, we just hang the .value + // and .done properties off the next function object itself. This + // also ensures that the minifier will not anonymize the function. + next.done = true; + return next; + }; + }; + + function values(iterable) { + if (iterable) { + var iteratorMethod = iterable[iteratorSymbol]; + if (iteratorMethod) { + return iteratorMethod.call(iterable); + } + + if (typeof iterable.next === "function") { + return iterable; + } + + if (!isNaN(iterable.length)) { + var i = -1, next = function next() { + while (++i < iterable.length) { + if (hasOwn.call(iterable, i)) { + next.value = iterable[i]; + next.done = false; + return next; + } + } + + next.value = undefined; + next.done = true; + + return next; + }; + + return next.next = next; + } + } + + // Return an iterator with no values. + return { next: doneResult }; + } + runtime.values = values; + + function doneResult() { + return { value: undefined, done: true }; + } + + Context.prototype = { + constructor: Context, + + reset: function(skipTempReset) { + this.prev = 0; + this.next = 0; + // Resetting context._sent for legacy support of Babel's + // function.sent implementation. + this.sent = this._sent = undefined; + this.done = false; + this.delegate = null; + + this.tryEntries.forEach(resetTryEntry); + + if (!skipTempReset) { + for (var name in this) { + // Not sure about the optimal order of these conditions: + if (name.charAt(0) === "t" && + hasOwn.call(this, name) && + !isNaN(+name.slice(1))) { + this[name] = undefined; + } + } + } + }, + + stop: function() { + this.done = true; + + var rootEntry = this.tryEntries[0]; + var rootRecord = rootEntry.completion; + if (rootRecord.type === "throw") { + throw rootRecord.arg; + } + + return this.rval; + }, + + dispatchException: function(exception) { + if (this.done) { + throw exception; + } + + var context = this; + function handle(loc, caught) { + record.type = "throw"; + record.arg = exception; + context.next = loc; + return !!caught; + } + + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + var record = entry.completion; + + if (entry.tryLoc === "root") { + // Exception thrown outside of any try block that could handle + // it, so set the completion value of the entire function to + // throw the exception. + return handle("end"); + } + + if (entry.tryLoc <= this.prev) { + var hasCatch = hasOwn.call(entry, "catchLoc"); + var hasFinally = hasOwn.call(entry, "finallyLoc"); + + if (hasCatch && hasFinally) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } else if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else if (hasCatch) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } + + } else if (hasFinally) { + if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else { + throw new Error("try statement without catch or finally"); + } + } + } + }, + + abrupt: function(type, arg) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc <= this.prev && + hasOwn.call(entry, "finallyLoc") && + this.prev < entry.finallyLoc) { + var finallyEntry = entry; + break; + } + } + + if (finallyEntry && + (type === "break" || + type === "continue") && + finallyEntry.tryLoc <= arg && + arg <= finallyEntry.finallyLoc) { + // Ignore the finally entry if control is not jumping to a + // location outside the try/catch block. + finallyEntry = null; + } + + var record = finallyEntry ? finallyEntry.completion : {}; + record.type = type; + record.arg = arg; + + if (finallyEntry) { + this.next = finallyEntry.finallyLoc; + } else { + this.complete(record); + } + + return ContinueSentinel; + }, + + complete: function(record, afterLoc) { + if (record.type === "throw") { + throw record.arg; + } + + if (record.type === "break" || + record.type === "continue") { + this.next = record.arg; + } else if (record.type === "return") { + this.rval = record.arg; + this.next = "end"; + } else if (record.type === "normal" && afterLoc) { + this.next = afterLoc; + } + }, + + finish: function(finallyLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.finallyLoc === finallyLoc) { + this.complete(entry.completion, entry.afterLoc); + resetTryEntry(entry); + return ContinueSentinel; + } + } + }, + + "catch": function(tryLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc === tryLoc) { + var record = entry.completion; + if (record.type === "throw") { + var thrown = record.arg; + resetTryEntry(entry); + } + return thrown; + } + } + + // The context.catch method must only be called with a location + // argument that corresponds to a known catch block. + throw new Error("illegal catch attempt"); + }, + + delegateYield: function(iterable, resultName, nextLoc) { + this.delegate = { + iterator: values(iterable), + resultName: resultName, + nextLoc: nextLoc + }; + + return ContinueSentinel; + } + }; + })( + // Among the various tricks for obtaining a reference to the global + // object, this seems to be the most reliable technique that does not + // use indirect eval (which violates Content Security Policy). + typeof global === "object" ? global : + typeof window === "object" ? window : + typeof self === "object" ? self : this + ); + + /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(102))) + +/***/ }, +/* 102 */ +/***/ function(module, exports) { + + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { + + "use strict"; + + exports.__esModule = true; + + var _promise = __webpack_require__(104); + + var _promise2 = _interopRequireDefault(_promise); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + exports.default = function (fn) { + return function () { + var gen = fn.apply(this, arguments); + return new _promise2.default(function (resolve, reject) { + function step(key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + + if (info.done) { + resolve(value); + } else { + return _promise2.default.resolve(value).then(function (value) { + return step("next", value); + }, function (err) { + return step("throw", err); + }); + } + } + + return step("next"); + }); + }; + }; + +/***/ }, +/* 104 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = { "default": __webpack_require__(105), __esModule: true }; + +/***/ }, +/* 105 */ +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(106); + __webpack_require__(54); + __webpack_require__(107); + __webpack_require__(111); + module.exports = __webpack_require__(7).Promise; + +/***/ }, +/* 106 */ +/***/ function(module, exports) { + + + +/***/ }, +/* 107 */ +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(108); + var global = __webpack_require__(6) + , hide = __webpack_require__(10) + , Iterators = __webpack_require__(59) + , TO_STRING_TAG = __webpack_require__(65)('toStringTag'); + + for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){ + var NAME = collections[i] + , Collection = global[NAME] + , proto = Collection && Collection.prototype; + if(proto && !proto[TO_STRING_TAG])hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = Iterators.Array; + } + +/***/ }, +/* 108 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var addToUnscopables = __webpack_require__(109) + , step = __webpack_require__(110) + , Iterators = __webpack_require__(59) + , toIObject = __webpack_require__(24); + + // 22.1.3.4 Array.prototype.entries() + // 22.1.3.13 Array.prototype.keys() + // 22.1.3.29 Array.prototype.values() + // 22.1.3.30 Array.prototype[@@iterator]() + module.exports = __webpack_require__(56)(Array, 'Array', function(iterated, kind){ + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind + // 22.1.5.2.1 %ArrayIteratorPrototype%.next() + }, function(){ + var O = this._t + , kind = this._k + , index = this._i++; + if(!O || index >= O.length){ + this._t = undefined; + return step(1); + } + if(kind == 'keys' )return step(0, index); + if(kind == 'values')return step(0, O[index]); + return step(0, [index, O[index]]); + }, 'values'); + + // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) + Iterators.Arguments = Iterators.Array; + + addToUnscopables('keys'); + addToUnscopables('values'); + addToUnscopables('entries'); + +/***/ }, +/* 109 */ +/***/ function(module, exports) { + + module.exports = function(){ /* empty */ }; + +/***/ }, +/* 110 */ +/***/ function(module, exports) { + + module.exports = function(done, value){ + return {value: value, done: !!done}; + }; + +/***/ }, +/* 111 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var LIBRARY = __webpack_require__(57) + , global = __webpack_require__(6) + , ctx = __webpack_require__(8) + , classof = __webpack_require__(72) + , $export = __webpack_require__(5) + , isObject = __webpack_require__(13) + , aFunction = __webpack_require__(9) + , anInstance = __webpack_require__(112) + , forOf = __webpack_require__(113) + , speciesConstructor = __webpack_require__(114) + , task = __webpack_require__(115).set + , microtask = __webpack_require__(117)() + , PROMISE = 'Promise' + , TypeError = global.TypeError + , process = global.process + , $Promise = global[PROMISE] + , process = global.process + , isNode = classof(process) == 'process' + , empty = function(){ /* empty */ } + , Internal, GenericPromiseCapability, Wrapper; + + var USE_NATIVE = !!function(){ + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1) + , FakePromise = (promise.constructor = {})[__webpack_require__(65)('species')] = function(exec){ exec(empty, empty); }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + } catch(e){ /* empty */ } + }(); + + // helpers + var sameConstructor = function(a, b){ + // with library wrapper special case + return a === b || a === $Promise && b === Wrapper; + }; + var isThenable = function(it){ + var then; + return isObject(it) && typeof (then = it.then) == 'function' ? then : false; + }; + var newPromiseCapability = function(C){ + return sameConstructor($Promise, C) + ? new PromiseCapability(C) + : new GenericPromiseCapability(C); + }; + var PromiseCapability = GenericPromiseCapability = function(C){ + var resolve, reject; + this.promise = new C(function($$resolve, $$reject){ + if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction(resolve); + this.reject = aFunction(reject); + }; + var perform = function(exec){ + try { + exec(); + } catch(e){ + return {error: e}; + } + }; + var notify = function(promise, isReject){ + if(promise._n)return; + promise._n = true; + var chain = promise._c; + microtask(function(){ + var value = promise._v + , ok = promise._s == 1 + , i = 0; + var run = function(reaction){ + var handler = ok ? reaction.ok : reaction.fail + , resolve = reaction.resolve + , reject = reaction.reject + , domain = reaction.domain + , result, then; + try { + if(handler){ + if(!ok){ + if(promise._h == 2)onHandleUnhandled(promise); + promise._h = 1; + } + if(handler === true)result = value; + else { + if(domain)domain.enter(); + result = handler(value); + if(domain)domain.exit(); + } + if(result === reaction.promise){ + reject(TypeError('Promise-chain cycle')); + } else if(then = isThenable(result)){ + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch(e){ + reject(e); + } + }; + while(chain.length > i)run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if(isReject && !promise._h)onUnhandled(promise); + }); + }; + var onUnhandled = function(promise){ + task.call(global, function(){ + var value = promise._v + , abrupt, handler, console; + if(isUnhandled(promise)){ + abrupt = perform(function(){ + if(isNode){ + process.emit('unhandledRejection', value, promise); + } else if(handler = global.onunhandledrejection){ + handler({promise: promise, reason: value}); + } else if((console = global.console) && console.error){ + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if(abrupt)throw abrupt.error; + }); + }; + var isUnhandled = function(promise){ + if(promise._h == 1)return false; + var chain = promise._a || promise._c + , i = 0 + , reaction; + while(chain.length > i){ + reaction = chain[i++]; + if(reaction.fail || !isUnhandled(reaction.promise))return false; + } return true; + }; + var onHandleUnhandled = function(promise){ + task.call(global, function(){ + var handler; + if(isNode){ + process.emit('rejectionHandled', promise); + } else if(handler = global.onrejectionhandled){ + handler({promise: promise, reason: promise._v}); + } + }); + }; + var $reject = function(value){ + var promise = this; + if(promise._d)return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if(!promise._a)promise._a = promise._c.slice(); + notify(promise, true); + }; + var $resolve = function(value){ + var promise = this + , then; + if(promise._d)return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if(promise === value)throw TypeError("Promise can't be resolved itself"); + if(then = isThenable(value)){ + microtask(function(){ + var wrapper = {_w: promise, _d: false}; // wrap + try { + then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); + } catch(e){ + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch(e){ + $reject.call({_w: promise, _d: false}, e); // wrap + } + }; + + // constructor polyfill + if(!USE_NATIVE){ + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor){ + anInstance(this, $Promise, PROMISE, '_h'); + aFunction(executor); + Internal.call(this); + try { + executor(ctx($resolve, this, 1), ctx($reject, this, 1)); + } catch(err){ + $reject.call(this, err); + } + }; + Internal = function Promise(executor){ + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = __webpack_require__(118)($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected){ + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process.domain : undefined; + this._c.push(reaction); + if(this._a)this._a.push(reaction); + if(this._s)notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function(onRejected){ + return this.then(undefined, onRejected); + } + }); + PromiseCapability = function(){ + var promise = new Internal; + this.promise = promise; + this.resolve = ctx($resolve, promise, 1); + this.reject = ctx($reject, promise, 1); + }; + } + + $export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: $Promise}); + __webpack_require__(64)($Promise, PROMISE); + __webpack_require__(119)(PROMISE); + Wrapper = __webpack_require__(7)[PROMISE]; + + // statics + $export($export.S + $export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r){ + var capability = newPromiseCapability(this) + , $$reject = capability.reject; + $$reject(r); + return capability.promise; + } + }); + $export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x){ + // instanceof instead of internal slot check because we should fix it without replacement native Promise core + if(x instanceof $Promise && sameConstructor(x.constructor, this))return x; + var capability = newPromiseCapability(this) + , $$resolve = capability.resolve; + $$resolve(x); + return capability.promise; + } + }); + $export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(73)(function(iter){ + $Promise.all(iter)['catch'](empty); + })), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable){ + var C = this + , capability = newPromiseCapability(C) + , resolve = capability.resolve + , reject = capability.reject; + var abrupt = perform(function(){ + var values = [] + , index = 0 + , remaining = 1; + forOf(iterable, false, function(promise){ + var $index = index++ + , alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function(value){ + if(alreadyCalled)return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if(abrupt)reject(abrupt.error); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable){ + var C = this + , capability = newPromiseCapability(C) + , reject = capability.reject; + var abrupt = perform(function(){ + forOf(iterable, false, function(promise){ + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if(abrupt)reject(abrupt.error); + return capability.promise; + } + }); + +/***/ }, +/* 112 */ +/***/ function(module, exports) { + + module.exports = function(it, Constructor, name, forbiddenField){ + if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){ + throw TypeError(name + ': incorrect invocation!'); + } return it; + }; + +/***/ }, +/* 113 */ +/***/ function(module, exports, __webpack_require__) { + + var ctx = __webpack_require__(8) + , call = __webpack_require__(68) + , isArrayIter = __webpack_require__(69) + , anObject = __webpack_require__(12) + , toLength = __webpack_require__(29) + , getIterFn = __webpack_require__(71) + , BREAK = {} + , RETURN = {}; + var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){ + var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable) + , f = ctx(fn, that, entries ? 2 : 1) + , index = 0 + , length, step, iterator, result; + if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){ + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if(result === BREAK || result === RETURN)return result; + } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ + result = call(iterator, f, step.value, entries); + if(result === BREAK || result === RETURN)return result; + } + }; + exports.BREAK = BREAK; + exports.RETURN = RETURN; + +/***/ }, +/* 114 */ +/***/ function(module, exports, __webpack_require__) { + + // 7.3.20 SpeciesConstructor(O, defaultConstructor) + var anObject = __webpack_require__(12) + , aFunction = __webpack_require__(9) + , SPECIES = __webpack_require__(65)('species'); + module.exports = function(O, D){ + var C = anObject(O).constructor, S; + return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); + }; + +/***/ }, +/* 115 */ +/***/ function(module, exports, __webpack_require__) { + + var ctx = __webpack_require__(8) + , invoke = __webpack_require__(116) + , html = __webpack_require__(63) + , cel = __webpack_require__(17) + , global = __webpack_require__(6) + , process = global.process + , setTask = global.setImmediate + , clearTask = global.clearImmediate + , MessageChannel = global.MessageChannel + , counter = 0 + , queue = {} + , ONREADYSTATECHANGE = 'onreadystatechange' + , defer, channel, port; + var run = function(){ + var id = +this; + if(queue.hasOwnProperty(id)){ + var fn = queue[id]; + delete queue[id]; + fn(); + } + }; + var listener = function(event){ + run.call(event.data); + }; + // Node.js 0.9+ & IE10+ has setImmediate, otherwise: + if(!setTask || !clearTask){ + setTask = function setImmediate(fn){ + var args = [], i = 1; + while(arguments.length > i)args.push(arguments[i++]); + queue[++counter] = function(){ + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id){ + delete queue[id]; + }; + // Node.js 0.8- + if(__webpack_require__(26)(process) == 'process'){ + defer = function(id){ + process.nextTick(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if(MessageChannel){ + channel = new MessageChannel; + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ + defer = function(id){ + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if(ONREADYSTATECHANGE in cel('script')){ + defer = function(id){ + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function(id){ + setTimeout(ctx(run, id, 1), 0); + }; + } + } + module.exports = { + set: setTask, + clear: clearTask + }; + +/***/ }, +/* 116 */ +/***/ function(module, exports) { + + // fast apply, http://jsperf.lnkit.com/fast-apply/5 + module.exports = function(fn, args, that){ + var un = that === undefined; + switch(args.length){ + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); + }; + +/***/ }, +/* 117 */ +/***/ function(module, exports, __webpack_require__) { + + var global = __webpack_require__(6) + , macrotask = __webpack_require__(115).set + , Observer = global.MutationObserver || global.WebKitMutationObserver + , process = global.process + , Promise = global.Promise + , isNode = __webpack_require__(26)(process) == 'process'; + + module.exports = function(){ + var head, last, notify; + + var flush = function(){ + var parent, fn; + if(isNode && (parent = process.domain))parent.exit(); + while(head){ + fn = head.fn; + head = head.next; + try { + fn(); + } catch(e){ + if(head)notify(); + else last = undefined; + throw e; + } + } last = undefined; + if(parent)parent.enter(); + }; + + // Node.js + if(isNode){ + notify = function(){ + process.nextTick(flush); + }; + // browsers with MutationObserver + } else if(Observer){ + var toggle = true + , node = document.createTextNode(''); + new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new + notify = function(){ + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if(Promise && Promise.resolve){ + var promise = Promise.resolve(); + notify = function(){ + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function(){ + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global, flush); + }; + } + + return function(fn){ + var task = {fn: fn, next: undefined}; + if(last)last.next = task; + if(!head){ + head = task; + notify(); + } last = task; + }; + }; + +/***/ }, +/* 118 */ +/***/ function(module, exports, __webpack_require__) { + + var hide = __webpack_require__(10); + module.exports = function(target, src, safe){ + for(var key in src){ + if(safe && target[key])target[key] = src[key]; + else hide(target, key, src[key]); + } return target; + }; + +/***/ }, +/* 119 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + var global = __webpack_require__(6) + , core = __webpack_require__(7) + , dP = __webpack_require__(11) + , DESCRIPTORS = __webpack_require__(15) + , SPECIES = __webpack_require__(65)('species'); + + module.exports = function(KEY){ + var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; + if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, { + configurable: true, + get: function(){ return this; } + }); + }; + +/***/ }, +/* 120 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('main', [(!loading) ? _h('div', { + staticClass: "wrap-content" + }, [_l((floxItems), function(item, index) { + return _h('Item', { + key: index, + attrs: { + "item": item + } + }) + }), " ", _l((tmdbItems), function(item, index) { + return _h('Item', { + key: index, + attrs: { + "item": item + } + }) + }), " ", (!floxItems.length && !tmdbItems.length) ? _h('span', { + staticClass: "nothing-found" + }, ["Nothing Found"]) : _e()]) : _e(), " ", (loading) ? _h('span', { + staticClass: "loader fullsize-loader" + }, [_m(0)]) : _e()]) + }},staticRenderFns: [function (){with(this) { + return _h('i') + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-6", module.exports) + } + } + +/***/ }, +/* 121 */ +/***/ function(module, exports, __webpack_require__) { + + var __vue_exports__, __vue_options__ + + /* script */ + __vue_exports__ = __webpack_require__(122) + + /* template */ + var __vue_template__ = __webpack_require__(123) + __vue_options__ = __vue_exports__ = __vue_exports__ || {} + if ( + typeof __vue_exports__.default === "object" || + typeof __vue_exports__.default === "function" + ) { + if (Object.keys(__vue_exports__).some(function (key) { return key !== "default" && key !== "__esModule" })) {console.error("named exports are not supported in *.vue files.")} + __vue_options__ = __vue_exports__ = __vue_exports__.default + } + if (typeof __vue_options__ === "function") { + __vue_options__ = __vue_options__.options + } + __vue_options__.render = __vue_template__.render + __vue_options__.staticRenderFns = __vue_template__.staticRenderFns + + /* hot reload */ + if (false) {(function () { + var hotAPI = require("vue-loader/node_modules/vue-hot-reload-api") + hotAPI.install(require("vue"), false) + if (!hotAPI.compatible) return + module.hot.accept() + if (!module.hot.data) { + hotAPI.createRecord("data-v-7", __vue_options__) + } else { + hotAPI.reload("data-v-7", __vue_options__) + } + })()} + if (__vue_options__.functional) {console.error("[vue-loader] Settings.vue: functional components are not supported and should be defined in plain js files using render functions.")} + + module.exports = __vue_exports__ + + +/***/ }, +/* 122 */ +/***/ function(module, exports) { + + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.default = { + created: function created() { + this.fetchUserData(); + }, + data: function data() { + return { + loading: true, + username: '' + }; + }, + + + methods: { + fetchUserData: function fetchUserData() { + var _this = this; + + setTimeout(function () { + _this.loading = false; + }, 800); + } + } + }; + +/***/ }, +/* 123 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports={render:function (){with(this) { + return _h('main', [(!loading) ? _h('div', { + staticClass: "wrap-content" + }, [_m(0)]) : _e(), " ", (loading) ? _h('span', { + staticClass: "loader fullsize-loader" + }, [_m(1)]) : _e()]) + }},staticRenderFns: [function (){with(this) { + return _h('span', { + staticClass: "nothing-found" + }, ["Settings coming soon..."]) + }},function (){with(this) { + return _h('i') + }}]} + if (false) { + module.hot.accept() + if (module.hot.data) { + require("vue-loader/node_modules/vue-hot-reload-api").rerender("data-v-7", module.exports) + } + } + +/***/ }, +/* 124 */ +/***/ function(module, exports) { + + // removed by extract-text-webpack-plugin + +/***/ } +]); \ No newline at end of file diff --git a/public/assets/favicon.ico b/public/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e0320f9c9d4e42ab260d17f9edf1bd2da8e2e713 GIT binary patch literal 1406 zcmeH{NlcSL6o9{~C@yFf#SImA+$$oBA|NUV;*V@rARauJc=2Mqka+OQ!5B3}4+bNI zL=GYn3kStDH3(u5TZ@FH6cB7JrRi$>x3w)EieB{QftkFS_q~}nGw;1*K;rLGDgH5> z3tYk58G#qD&RRbo== zd61yPA-_p={21oqJ2*an$6a!bzQP6!9d`7!J$NVVyw7Z*A!~&3Pj)OH4ERJZmVPI0 ztB6`?rYTj8_PPdDwt|r-2D~njkLA6L*L9<*9K+OR!d%mdt-cFmqZX&$iLb1JN6EeT zd_JC)>X>*jLT~Ov-j=8sy7V0Jn}yC>COkGb?qM^-d9}E{S`i&yhH8dF3NWosXW&1` zK-_LwThYN|(TNdj ygxO1jEZZ_qShQizq0CK_=gT6OuRXQ1Y-8H5`$OaT3?$zOPHh5GLIFM@u0Z-fDzFP$YXuZ#EeY}q zW+-=2nweX8%>yW)@9E+gVsScIf|Z$h3Qxhw7A_uX$uw03j#4Het_-7|g$4o*(PmdKI;Vst0NSH4=>Px# literal 0 HcmV?d00001 diff --git a/public/assets/img/algolia-dark.png b/public/assets/img/algolia-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..92f747f6d6fc455a7c2701ac8bac411a8ec3aba5 GIT binary patch literal 1327 zcmeAS@N?(olHy`uVBq!ia0vp^0YEIt!3-oP&WN;TU|=i>@Ck7Ra{m(toOeAWsL*ZQ zZMd4h|NgmbyaVUL8Lk^|LD=r=?s#u}=)U@X!20_@5!-!_+}7O!Bak8P>p;qo4Fqx_ zz+>%wAj54v!Y+^XcR?a+Z@R9(<-7qZ?y>=D5kwc9bXyN~mD^g7O3yVQuKT)2u1JoD zD0W+a7ibGafy>Sb*L6>TBoF|7=f3u)yYjzOV7OP71o;IseBEol#O0qttX+=DLtV~a z7f$$my0cl0=jG$8ryEiuoMgmUclA_PR#=&{Cjch`nl~(7SC@fNQe#z4h%3- zmSz6+{r%eqrw*=NK4;p5?#{Nx`lNVIPc2PFDZ%&m_itada?bSP+-x^J`R`Yc?I?%{ z4Yn5(5#%pkr0T`M!1U46#WBR<^xDhm!H)t&j(ueI2x}H$UE&og;PPhg_j}c`zoWK& zfBxy|_j}nqDXDFDCI9OeJ>T=wchcm5nIZ4RLUR_KmswoDhHrYv#@Gil( zAl=k4DlH`N=&Ho3!~MJqI!~pr8^j5o>0c65&BtuP!V^3*j8P|)<+#NAxr{2Sr=Aii zUhEzirPX-z#lwd;%9SJbrBytNeNoML?Dge`w*!CYFOs(oT(olI+_@VynO|&7@u|JKd+)9j@$|UHhIpo5HXOdE>zx{=Xq9xi z=gxh5wyevy-n1bqyPz{!nsL4W(+(ZR+yimTThuIgAc$r2TUkrPn9@5>>&~9_3EV1}!%^+L?x`y0JLZQ~fyM?AEaeMtbSJd2 zc0S+n`25`WDg5<~y?G~8B3hFcDp~Md5jn{I?V4j$AKx_7CSkuFt8(3S|1$N=Ph9v; zlV4;u-!0J=&v>tOi*22wE;1eGePH%1`ImK0OOoP5lUXGOf=&A!_dD-O6kk$$&djsH zkoU@V?^O(ElP+*2F6>>wE`KzD|H>+}(+j+tZtgtPTl3;hY2v%UH$EF*BuJ_4E^B|J zoOA8qmOmo17p%GSIr9SNOeKe3W`~dlhqrZ)|~d^`8vJ9_lq-sid3*XIk)U6B=2*SX#hY<;~X6p1`aLgiZ|mbD}n zW11n4ET;9WMoWk>V+?wTCM2Y-cCT&!xaXdG?(h80@0|PH44NNhixx}^0)cFydU?{p zP6NwGLlxMZf?y{IWK%WGH;@F5NE{1^V*+c8WB=!~kXR-X%R=JW2m%X%W9{XpY{ao_ z1TGM6$3|e82rLVR_J`Rq;Py;7I)Gd^j<5%SjYNQlqiAq6V}~tc2a0247eH)~!|dtA z2Q&W{0z4p#0QgznJUJ2v2!jB_x6%~eIGH#8jfw(-ST-EbM538+EZZ3PSSFb-rPN80 zcnf7eY&8^WT}5Saf%t<@d8Q zicztkCNAo9co>%xKt%1`Wu&{lARX#|*wWNcdH1*Cg8ZA;GLkQb29of*%}h*;3>TGS zBOUjP6XH)Er+HJ+#`^OwXQmY6%}tHfRlk;GrN%~vGZ}6!4rb8h?yy@Bh^ju-lNd;N z!W&*=z=#IWMQA~n2W`J&j_K8uwjTL~Y}f_rLfe|WqxJJ&k`O)v&%ZFDvGeK}C|UgQE|AMFn~|L;UnzfI#hae%qa1wX??-wXG|=ggxu9?HQ_y zb3Q3cyt=ynN%ebMXKkOyt0FKK4>#?Kl0xV))$E@dG)I-Ig>*&V>f)kks~Ow5sd?xk z$&Ne_V&ol**Ur|>PDGf;6C#&iiK;ez$jyuEnvVHkIiK<+{Zl)~(*K!yVHtU#bqXp< z&PTP0-yTeO9cJ2|N7<}6R_bfrdUNWlymmlj1C8bq`yla#p1mh3A87^-N|l4uo;n`C zBck@?KemzLaL3S5N#BZ~KkSgRQ)ETsw&6<_P3%s+hVDv?(y0t4zx~v=_j)Ssetkqr zO>xed;U{Zq9ifo;Uo^&!IG7VZ<;I-}Feq>D&Y{LiHC{y-?`t`z@OP%4zxGrGrG3Qm z@aF10^89tHOq(9p(}Gn(v5k6($7M&o;os3$dyX2{8uH>I)3BA{OLy1(J`Gw-cFu6k zCAu2X;@$VOyqJ&EE|oZsK?&~_syLFVz-czW-sAd2aE@I$>daZQc$r2fpGr}~q1xT#03m=~OiaJwN=ikAy?{}9X*^Z%aBIP->Zl=lBpa&BV;>dUTdRhrLZL#nb`U;EG7`UXC0{Wjd@$M*cvn4W z!HWBRxdF{AeKhUF=i$=ri96@-yYdN@#%J?f(>VNuTW@a;6=f=wnMHPOO;It~v$P@E zoN;W?fwMkD8&XBt^~fwg)AT*-(h|&pgk(Q+mjaD~2o8b&F~*(iQy!imo5n8;CcW6Y XePVuMs<5{Pd|C*V6W3ar_UQ?C|A)h02`267@cJt&hj= zI&QvbMbxEvUZJi9tFAlT=-EHxvb6DUt>$nER+l#)y7V?3?`^Ubikr;W9WA``fowO+ z{fDx1+eP0;E_{AKC;Ha&OxZ&ZwpIG?wq7UdrozUZ{-)u`iLM0?rDY>7%8Mu8Rco9$ zd-HMIF9I(-Z>r60m>Jb|#eY-#%(9F7;+}kc@NB_O{jf(oS2r9=b}n3~@#Rj`vL>EA zUQ3j{@3C!lW?3NHGHq4IqMffBWoGWY`D)pjj;VZKp9q}_F)_HMev;e%zNTt`%MZ6y zk*>ox4k`IRzLb8ZUiht3y-#OY7H^cdboc3w)9IR70x>ztJlmT&zJ{p3cS~eRKJwyE b;s<80t41H1H*NC+hBSkxtDnm{r-UW|&_NH< literal 0 HcmV?d00001 diff --git a/public/assets/img/logo-login.png b/public/assets/img/logo-login.png new file mode 100644 index 0000000000000000000000000000000000000000..bc852b45a08f9e1cceee876bf220cb6750398819 GIT binary patch literal 1552 zcmW-g3pkT|9LJYi;;D#($EC(mPUUoH3Ui6s*ya-EPR~elx~w{g< z;r``1HD^}X=-7MDcXj$maSM*WXqwlI6Ts>NpU*|dr^{U5 zE*yR=HOYo~kb(_8$C^QBz~)8IF}B1sH^Xl&-{bFh=4CG(`}%Dfz_gk;_KY~n!FKoB zHomd09i2Gn*3ZVh4h z!_g8T=V19WM~Y_5ihx#RQ3Wnw%Et8o6$jfTM&-XhTDoYOyJV8n;3Nd9YUfda9Jj27 z3cPgc6WTO@S4!X}&%Uj~WkO_837V7U<-=ArUG}XbXjZo!rMIeDXKrh-II$N<_y|zt5R?n-Q$KZ7qaTp-M4lp_}9Y6x)OQt!{ z8ekTq3ZMnhKIjglgVgDM>;JdoKZcJ-ih&kt2&oI*XYxGfA!(`W)PsGP1o$kHFL}C= z5Z)qhkupjZ<*lkG5}{=2D1CKNBMG}-QS{#-z#1FxS6`CAaC}_IYin(3t}83c%Vnge zr_<@NG%}flMe9i;J z6-T}ObSfY$?5cf?H%kVSBDp%Ak}OXTjf$bfehVf3NJ>&UaEUfB+Y&!{cf&78P@?Eb zo2Fh~yO3t1d*+N#C=3s;U+0H}APFwt1WonS3x}R4nQUa)OR*2MFCy~vs)mPbSK>dc z8FKj1uZi929UoAhESg%8QvA8%NOfyGl6w6V+e$7v#NfyNvIcY-#TBRRD%@+F&ATOs zeOTk8oL#N@iRhuRqZ!XX%i5Pw-u$zNez{qxp?ufdp!TC|(oP*M#WnRz4xm# z&}9RzU@o6F8*v4riiMnDlU6gzQ%64{(Z-rCt+@BQ7%@SL}>s?R5Nw zC||wdP|?@q_a(BV^>t=WC$S)SA|j}Or04%D*PC@bC?SdvjKkq2z%;~iE z@#Ygc?FMWR`d2zQND@7o*w{4KIVZ!m4)4^aXrT@vFC9eOU}{X6e^I$va+(?VR8TLS z#;fn1u-6Vwx{&BDf4{3L;>8I|8#mu`Q_)}Ie>?eDCu%A)H7-<>>X=O&k>Q11i~Q%k zKbcHx2%^{zT`a;GNBp@vaZXiizJ?rJs&>%*9Do|8tkM||Juc4n8`ncZ$@W(L2yZMpW1;k<3`7k0Ux+2DC~kISj~ z0Z*@5Z3c>5w%Gzyu-y0V8T;KpWe~*&oR4)z{(NIJceVG;6At_51U|oRwE<}6Zr4+A z?h^k87i_n0_PDg(>ncS1f`BJL_7SH;?NPsnC%5HZ*2hk_yN=lv<{*L=$O|=^MMWnx)5j}&?7)EK%4}$ z_nmF%0$|`ql?3?(GYAOSbM0EUZt9d+9*&0(?_KJw_El4p75@PQ-@ku-|Nh;(=g%Kq zxNzpo-o1NvY}&M9@#1MyCQs-Cg6{6B;(~(A%%r5SFb@w0dt+lA9aUBFuTLJ{*t=?3 z$;lKkYhY9=d%8G=Xq<1I99qs~DA3BxExN!p`qjI2SMJ{J-o5+Je|ELWtYwEEro^Qc zKeIMBHs8ENRO)3?_1R4e?(eL*HtE}sT~U(jM7mxUn1snj?k)TDb@$SceRmkLmY(^v zcU6v+q}Qs(H!oIt7FJI`@80;bboRl5W%Cy{+`qpz_i8goj>nrnTRI(9cz$6MurLv_ z>~ZIC`F7)@TEhXcz!vGoAG&}4&2Ue+);QI1_1tBRmMmxHe`#W2VsBx5*jX$4B$=hi zwq=ixlEJqF44lVo+W%Pe9k`->(^uib_hT&o7$aCZzt^!iJo0CgF<5stb)nl|i-nw$ z2HK(~`yZ&RU-0T6H^cqrEUvk)tZ>(B3Lp{K>L- z?JMW4t(t2mEpRos`Al;2J{9%fKbk&1_m!_==~#Kjsb#WnZ7gRn?=`otCIJ<3(e0CS z#dpNtaNer>+wajn-ECKPi!A-A(R9*GSigwpti!8yC(elPO;;d7>wC$zRGuL=!mXujN{mTVcg{z;^xQICT4n}FGK*8I)soKS4UXSt}?w5xVS zuZoAkoHNIG#95n?{)Z`eIW=!9UHV0PdR@S;l;Di$aQRm*-V!!fRQe@yUvusLb$kA+ zPX!v)+KFYYX06*wdj)6zec8G<(d~|GW{79YMrqq57p|~}+Xb$xhfJ57C%U$6&ee*| z8y9TLTYh3&)5#wPF3Yjco5pJ+%cG|j%Qk_vw`j`T9amY6@^rF}OgQ!1Eq1TNv4w$Z z@1H;ZUaii%MYDLG&Y_RhcS6>=?~BOL%$}z^^~Q<&RjI%D9k^yG9@_eW519NIJYD@< J);T3K0RVz1&T;?% literal 0 HcmV?d00001 diff --git a/public/assets/img/rating-1.png b/public/assets/img/rating-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d61a0f5d6a40ddec6219030e0d1797e80b620d95 GIT binary patch literal 584 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=3?wxlRx|^tnE^f_u0Z<#pafTCSwcWAE(!7r zW=Q}1QfK*8rk{`Q-Z;2njjt-}n|Upj1#Xto9Gk?2`Ols@x@*$Jj>g)o*zh0&g$w5w zB`Tc!_=|yoQODE8F~sBe+e;^lnhki^5{@1`Xl9+rDX{6igV^5xhfSBveQ9#Vx%6e{ z{{_s4)%$f1PEg$cbkUPKN1?{G?@st~om{VX#A5M;pdy1KolaV77KkY~8RTwd;16b+ znaHytRkg9;nuA{KCB?vKxhb<-BoA~-KD%T7$Da2~%gN2hPUIeC*}N@s{f7-1$K#?O zU;Q$}g>~IC+eK;D&u@$Tyftq|#`F}ETD7Ql-ajXrT&;>6R!$L`J5Mxgd%~M1jsg`G zb-&-8?(J*YeVzaAyy|7Psh7eQd+%5xCsHDXBA5(N!TiVY>^f?DVcu3eERX< zK|i95%FbT@Ewky;pMAdrKR9@Q%h1jDZtGZ>n$LCoVR@c$iT4FHf0^T&YA;pq?VSBJ nt8(*_t@oCx@koA}|C2%YoWyn2AU6$Qs55xF`njxgN@xNAj5}A$ literal 0 HcmV?d00001 diff --git a/public/assets/img/rating-2.png b/public/assets/img/rating-2.png new file mode 100644 index 0000000000000000000000000000000000000000..5b72418a0ba0d78780ec00b8ee6800cf455e56e9 GIT binary patch literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=3?wxlRx|^tnE^f_u0Z<#pafTCSwcWAE(!7r zW_XpZ^JV!|re6X*6&?afZk9-v9cTrI%LiSetr9Z_~py zJN#vAe?}QaMgCNe-u<%Xd&Shh1^Zvrt8Zgym~@Jj=ebLc2ulOo?-On(B>8Obw6tYi z+_ias(K}feFBaa(wQoA6NT>131i3DW;W0CRq$`*B*-!Y|8rvH+W+5$I9(l=Am%n&3 zZMVym<*kiD3VU7|P44Vum)J7fR*Nx2=4r~NN}gL5wg0O!WS-9XZ)VGLM>f#X?>n@U=UA44$rjF6*2UngIFaPG|rC literal 0 HcmV?d00001 diff --git a/public/assets/img/rating-3.png b/public/assets/img/rating-3.png new file mode 100644 index 0000000000000000000000000000000000000000..213c7db99cfc70cb77a5750d3813c4e1ca40537d GIT binary patch literal 581 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=3?wxlRx|^tnE^f_u0Z<#pafTCSwcWAE(!7r zW=Q}1QfK*8rk{`Q-Z;2njjt-}n|Upj1#Xto9Gk?2`Ols@x@*$Jj>g)o*zh0&g$w5w zB`Tc!_=|yoQPb1KF~sBe+lwdjnhgXR9v(b+(9F7V!{l1k*L(gS7G32f+Ql(9TJ)p* zvu|f3jCy+izTdPn_x4W{JNM}Hy-|AamYIalzER;^mZA5KyRD-!b8YeMXZ(4FC8z3) z3U9Rh=_Drp5TVDN zUNM3}oCTI2^w*~xuUda&=KJ68PM@~j`A)fdikD_%@r$s<*W8VAuZgT{(k@vQ!SR0g zhG?$bm;AQo5QrIa3&UAmI4>t%60~h6m61ay3haO)#7A((U2PIM#a2 zgBxW16^`5#HF_D~(Ij}FZ7NGr#40B7WQCAqUh##29-5Xf9(gF$L0-n#>|hdoZU7tE5zT^T3bQ#_OZP)3N1wHMcdPW>U%t0977~7 zyPk9BJ8Zz?a&e-}$+DQo_bxsEmu@01^f&wnGow&mJa5uF_6I-q_KD#)IMa8#{-3mM z(oL4tPioFD@0rNLwN0#H(#jdVd=o!ON_g`t1Z`qW3m32|VA`~mYp=QV@jpO!F?hQA KxvX!jW;GRnF%N{%hSa%gyVX0LPEk5hE9b-2K w*DTHEs~?xVDVuvBCF2MK^QlV(YLodHQYFO&^W3kQ0bR-9>FVdQ&MBb@03UB)tN;K2 literal 0 HcmV?d00001 diff --git a/public/assets/img/search.png b/public/assets/img/search.png new file mode 100644 index 0000000000000000000000000000000000000000..084e1473fb89e0d387389b5a04bb93d454f9d595 GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqJQamH|E?u0WbRu%|4*7N}FWB*-tA zAud$ZPAgE5!%ZdH!ds5l&&r7Bn{PExdX}e)V~E7%(g~h?M+`Vv?&{o=RsZ=v*k zL+Y=F07hP=8GM$VZqFY)YE+#mZ!M)THIiH4@~do#J*Qe`=t@icl=f=L3*GYMo9Nq( zq8>Ly7K***+x=CbqP^=A|GW#bTzbZu(x+3jB`jp_E%?JH@O$QI9ru9R&C(gG6K1pW{$nuZWj@$)pk+SD`<||TF6*2UngG_g BSUCUy literal 0 HcmV?d00001 diff --git a/public/assets/img/sort-star.png b/public/assets/img/sort-star.png new file mode 100644 index 0000000000000000000000000000000000000000..dcc0ad41c6fc52d7c1a5eee0cf74eefc20abd508 GIT binary patch literal 492 zcmeAS@N?(olHy`uVBq!ia0vp^3P3E!!3-p;uDp>3QaJ%WA+A9BKfQpR|AR1~eJUkE ze!&c9W;XljAKbEMu1Z%`ki3M@ild85!o8e~d0E%4pWj!Xmujx59r@=D0|O(sr;B5V z#`)SwFZ&KF@U;At5@NEvbtm`I?)U%uw42J5-D98iOCIaV$=T{0yIO;%3ww8Zs|c5|et|?0B3^~4R#*TWsEgy@3wr& zv0ZtM_GSOtG41{gprF+)3*v^WXncU;e>R(R=^POt(kLCpumlIlqc_ ztDg32=ht6t?76yPtDi1p;c@@SE3q>E#1q$JuG3nka*9QkxoQe~X&tO?E10oNfc@9q zb!&3>S--fKJ$v`s$mNrwcHBL%>@|!BKiC5TKAumAHV-CKVd58chk}yGhi?>c)I$ztaD0e0svA{3t0dF literal 0 HcmV?d00001 diff --git a/public/assets/img/sort-time.png b/public/assets/img/sort-time.png new file mode 100644 index 0000000000000000000000000000000000000000..93796bcb3dd4b1f49feb76e8bd44343cdc59d88c GIT binary patch literal 453 zcmeAS@N?(olHy`uVBq!ia0vp^3P3E!!3-p;uDp>3QfUD`A+A9BKkdQP`I#$#HYt?^ z`2{naVPiU89%CdWvUyGIpLJ=OKB_p?kfW1ho}5B3HWnq=6zY`it)vQ)cO z?WDspT*ZO=Ejup?wC=kX`J>?EE4I+*Z@0fV|J8}7Y_8x!>4)b8*ZyjJQMu1z+A`Dh zg$i$G-zr_iGoRP%vga(8ina%BU+gaCNlN)Ga^9U75YjJwZo;PzTbGD_?lEfciMn-E zFzAH9gGXs`hg95euuCS!?5$)?OY5}W{(f)y&VTGuYLP*W?30()2eN*Dz|r=4;XQ|< zCF-;Owa!~vYiZ+r^WCYp5vSPiG8nJ=TQ`CCvTcQO9Rt%9_5}OlgEc^ZGkCiCxvX6fz(Pv2Hoz`(%VTXVnHZ?@Fz zD*W>-Y1#WwbI8wJ~Q4kapF>)7~7>bzoxOx?ulC!8*%*qm*87} zE>-v~s<|bpy{LG3@zVDz7{!m9dtZ9Vqw(s7`7i$34PgQWOY7bWx85{L{~{|p`%Y;7 zv?-Ntw$E(;Mq9VpZF*F=L;tXzGk;=cG5dDK&%IKm=R9s)=3lVoNLJjvEoNz{@6w-5 zds2PUckjLO(0lz?cc1=LxVE>F+518w;oy=G*Kt<}x^8XpE+6gh0%daTyo;R3NnsrJFI6ZY&QKAs9wfs z7J1FqEAK^>T*Ad)PgxytnTrvJ01`=8;?U_SYwsQy#?5utSE zE5<7pJ-)QPMfGrVoPBfN)o0hdYIu20&x$cV5WVyFBj@Q4589|Qb@LtH%O1Mx#K(Ez zI{r)3%lXCJx3Qi0^ls} zTPtDFPj{EI@IIa0?vv)XoBQXp{>|G=xJw&lX042MS2xSL{@;qnfY1(P*vn%ZsJ)puQqPxhO-Wxj7pIkS=Hx{nU>`&7O~g}1zGNIcB6 z_FJUAZ`o;Q!P(8zjY77xELHw&Um)=*@N}n$rfT$>+P5jbR}cSi;QG2{#Ze{8Hiowh zib;Xzl~%@XwW$kG{Bj}r&_>>A`={ux`mN;q{nds&Pq#$H>0D4xjYzmOjny>obo0h_ zhl|2fh1;rErf<}-nejWdUd8Xw5o?`~Av~u-u1V`kHU_SqGJDrap~!fNd%|8{m`hT_ wjy(9uI7zr6FAd0B-_}{z5_Wq>xX@oFcF%QFPTme{0%m9iPgg&ebxsLQ0Ayr_{r~^~ literal 0 HcmV?d00001 diff --git a/public/assets/vendor.js b/public/assets/vendor.js new file mode 100644 index 0000000..6638f47 --- /dev/null +++ b/public/assets/vendor.js @@ -0,0 +1,9576 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // install a JSONP callback for chunk loading +/******/ var parentJsonpFunction = window["webpackJsonp"]; +/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) { +/******/ // add "moreModules" to the modules object, +/******/ // then flag all "chunkIds" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0, callbacks = []; +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(installedChunks[chunkId]) +/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]); +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ for(moduleId in moreModules) { +/******/ modules[moduleId] = moreModules[moduleId]; +/******/ } +/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules); +/******/ while(callbacks.length) +/******/ callbacks.shift().call(null, __webpack_require__); +/******/ if(moreModules[0]) { +/******/ installedModules[0] = 0; +/******/ return __webpack_require__(0); +/******/ } +/******/ }; + +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // object to store loaded and loading chunks +/******/ // "0" means "already loaded" +/******/ // Array means "loading", array contains callbacks +/******/ var installedChunks = { +/******/ 1:0 +/******/ }; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) { +/******/ // "0" is the signal for "already loaded" +/******/ if(installedChunks[chunkId] === 0) +/******/ return callback.call(null, __webpack_require__); + +/******/ // an array means "currently loading". +/******/ if(installedChunks[chunkId] !== undefined) { +/******/ installedChunks[chunkId].push(callback); +/******/ } else { +/******/ // start chunk loading +/******/ installedChunks[chunkId] = [callback]; +/******/ var head = document.getElementsByTagName('head')[0]; +/******/ var script = document.createElement('script'); +/******/ script.type = 'text/javascript'; +/******/ script.charset = 'utf-8'; +/******/ script.async = true; + +/******/ script.src = __webpack_require__.p + "" + chunkId + ".app.js"; +/******/ head.appendChild(script); +/******/ } +/******/ }; + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ function(module, exports, __webpack_require__) { + + __webpack_require__(39); + __webpack_require__(45); + module.exports = __webpack_require__(40); + + +/***/ }, + +/***/ 39: +/***/ function(module, exports, __webpack_require__) { + + /*! + * Vue.js v2.0.1 + * (c) 2014-2016 Evan You + * Released under the MIT License. + */ + (function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.Vue = factory()); + }(this, (function () { 'use strict'; + + /* */ + + /** + * Convert a value to a string that is actually rendered. + */ + function _toString (val) { + return val == null + ? '' + : typeof val === 'object' + ? JSON.stringify(val, null, 2) + : String(val) + } + + /** + * Convert a input value to a number for persistence. + * If the conversion fails, return original string. + */ + function toNumber (val) { + var n = parseFloat(val, 10) + return (n || n === 0) ? n : val + } + + /** + * Make a map and return a function for checking if a key + * is in that map. + */ + function makeMap ( + str, + expectsLowerCase + ) { + var map = Object.create(null) + var list = str.split(',') + for (var i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase + ? function (val) { return map[val.toLowerCase()]; } + : function (val) { return map[val]; } + } + + /** + * Check if a tag is a built-in tag. + */ + var isBuiltInTag = makeMap('slot,component', true) + + /** + * Remove an item from an array + */ + function remove$1 (arr, item) { + if (arr.length) { + var index = arr.indexOf(item) + if (index > -1) { + return arr.splice(index, 1) + } + } + } + + /** + * Check whether the object has the property. + */ + var hasOwnProperty = Object.prototype.hasOwnProperty + function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) + } + + /** + * Check if value is primitive + */ + function isPrimitive (value) { + return typeof value === 'string' || typeof value === 'number' + } + + /** + * Create a cached version of a pure function. + */ + function cached (fn) { + var cache = Object.create(null) + return function cachedFn (str) { + var hit = cache[str] + return hit || (cache[str] = fn(str)) + } + } + + /** + * Camelize a hyphen-delmited string. + */ + var camelizeRE = /-(\w)/g + var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) + }) + + /** + * Capitalize a string. + */ + var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1) + }) + + /** + * Hyphenate a camelCase string. + */ + var hyphenateRE = /([^-])([A-Z])/g + var hyphenate = cached(function (str) { + return str + .replace(hyphenateRE, '$1-$2') + .replace(hyphenateRE, '$1-$2') + .toLowerCase() + }) + + /** + * Simple bind, faster than native + */ + function bind$1 (fn, ctx) { + function boundFn (a) { + var l = arguments.length + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } + // record original fn length + boundFn._length = fn.length + return boundFn + } + + /** + * Convert an Array-like object to a real Array. + */ + function toArray (list, start) { + start = start || 0 + var i = list.length - start + var ret = new Array(i) + while (i--) { + ret[i] = list[i + start] + } + return ret + } + + /** + * Mix properties into target object. + */ + function extend (to, _from) { + for (var key in _from) { + to[key] = _from[key] + } + return to + } + + /** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ + function isObject (obj) { + return obj !== null && typeof obj === 'object' + } + + /** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ + var toString = Object.prototype.toString + var OBJECT_STRING = '[object Object]' + function isPlainObject (obj) { + return toString.call(obj) === OBJECT_STRING + } + + /** + * Merge an Array of Objects into a single Object. + */ + function toObject (arr) { + var res = {} + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]) + } + } + return res + } + + /** + * Perform no operation. + */ + function noop () {} + + /** + * Always return false. + */ + var no = function () { return false; } + + /** + * Generate a static keys string from compiler modules. + */ + function genStaticKeys (modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') + } + + /** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + */ + function looseEqual (a, b) { + /* eslint-disable eqeqeq */ + return a == b || ( + isObject(a) && isObject(b) + ? JSON.stringify(a) === JSON.stringify(b) + : false + ) + /* eslint-enable eqeqeq */ + } + + function looseIndexOf (arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { return i } + } + return -1 + } + + /* */ + + var config = { + /** + * Option merge strategies (used in core/util/options) + */ + optionMergeStrategies: Object.create(null), + + /** + * Whether to suppress warnings. + */ + silent: false, + + /** + * Whether to enable devtools + */ + devtools: "development" !== 'production', + + /** + * Error handler for watcher errors + */ + errorHandler: null, + + /** + * Ignore certain custom elements + */ + ignoredElements: null, + + /** + * Custom user key aliases for v-on + */ + keyCodes: Object.create(null), + + /** + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. + */ + isReservedTag: no, + + /** + * Check if a tag is an unknown element. + * Platform-dependent. + */ + isUnknownElement: no, + + /** + * Get the namespace of an element + */ + getTagNamespace: noop, + + /** + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. + */ + mustUseProp: no, + + /** + * List of asset types that a component can own. + */ + _assetTypes: [ + 'component', + 'directive', + 'filter' + ], + + /** + * List of lifecycle hooks. + */ + _lifecycleHooks: [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated' + ], + + /** + * Max circular updates allowed in a scheduler flush cycle. + */ + _maxUpdateCount: 100, + + /** + * Server rendering? + */ + _isServer: "client" === 'server' + } + + /* */ + + /** + * Check if a string starts with $ or _ + */ + function isReserved (str) { + var c = (str + '').charCodeAt(0) + return c === 0x24 || c === 0x5F + } + + /** + * Define a property. + */ + function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }) + } + + /** + * Parse simple path. + */ + var bailRE = /[^\w\.\$]/ + function parsePath (path) { + if (bailRE.test(path)) { + return + } else { + var segments = path.split('.') + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { return } + obj = obj[segments[i]] + } + return obj + } + } + } + + /* */ + /* globals MutationObserver */ + + // can we use __proto__? + var hasProto = '__proto__' in {} + + // Browser environment sniffing + var inBrowser = + typeof window !== 'undefined' && + Object.prototype.toString.call(window) !== '[object Object]' + + var UA = inBrowser && window.navigator.userAgent.toLowerCase() + var isIE = UA && /msie|trident/.test(UA) + var isIE9 = UA && UA.indexOf('msie 9.0') > 0 + var isEdge = UA && UA.indexOf('edge/') > 0 + var isAndroid = UA && UA.indexOf('android') > 0 + var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA) + + // detect devtools + var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__ + + /* istanbul ignore next */ + function isNative (Ctor) { + return /native code/.test(Ctor.toString()) + } + + /** + * Defer a task to execute it asynchronously. + */ + var nextTick = (function () { + var callbacks = [] + var pending = false + var timerFunc + + function nextTickHandler () { + pending = false + var copies = callbacks.slice(0) + callbacks.length = 0 + for (var i = 0; i < copies.length; i++) { + copies[i]() + } + } + + // the nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore if */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve() + timerFunc = function () { + p.then(nextTickHandler) + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop) } + } + } else if (typeof MutationObserver !== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // use MutationObserver where native Promise is not available, + // e.g. PhantomJS IE11, iOS7, Android 4.4 + var counter = 1 + var observer = new MutationObserver(nextTickHandler) + var textNode = document.createTextNode(String(counter)) + observer.observe(textNode, { + characterData: true + }) + timerFunc = function () { + counter = (counter + 1) % 2 + textNode.data = String(counter) + } + } else { + // fallback to setTimeout + /* istanbul ignore next */ + timerFunc = setTimeout + } + + return function queueNextTick (cb, ctx) { + var func = ctx + ? function () { cb.call(ctx) } + : cb + callbacks.push(func) + if (!pending) { + pending = true + timerFunc(nextTickHandler, 0) + } + } + })() + + var _Set + /* istanbul ignore if */ + if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set + } else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = (function () { + function Set () { + this.set = Object.create(null) + } + Set.prototype.has = function has (key) { + return this.set[key] !== undefined + }; + Set.prototype.add = function add (key) { + this.set[key] = 1 + }; + Set.prototype.clear = function clear () { + this.set = Object.create(null) + }; + + return Set; + }()) + } + + /* not type checking this file because flow doesn't play well with Proxy */ + + var hasProxy; + var proxyHandlers; + var initProxy + + { + var allowedGlobals = makeMap( + 'Infinity,undefined,NaN,isFinite,isNaN,' + + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + + 'require' // for Webpack/Browserify + ) + + hasProxy = + typeof Proxy !== 'undefined' && + Proxy.toString().match(/native code/) + + proxyHandlers = { + has: function has (target, key) { + var has = key in target + var isAllowed = allowedGlobals(key) || key.charAt(0) === '_' + if (!has && !isAllowed) { + warn( + "Property or method \"" + key + "\" is not defined on the instance but " + + "referenced during render. Make sure to declare reactive data " + + "properties in the data option.", + target + ) + } + return has || !isAllowed + } + } + + initProxy = function initProxy (vm) { + if (hasProxy) { + vm._renderProxy = new Proxy(vm, proxyHandlers) + } else { + vm._renderProxy = vm + } + } + } + + /* */ + + + var uid$2 = 0 + + /** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ + var Dep = function Dep () { + this.id = uid$2++ + this.subs = [] + }; + + Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub) + }; + + Dep.prototype.removeSub = function removeSub (sub) { + remove$1(this.subs, sub) + }; + + Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this) + } + }; + + Dep.prototype.notify = function notify () { + // stablize the subscriber list first + var subs = this.subs.slice() + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update() + } + }; + + // the current target watcher being evaluated. + // this is globally unique because there could be only one + // watcher being evaluated at any time. + Dep.target = null + var targetStack = [] + + function pushTarget (_target) { + if (Dep.target) { targetStack.push(Dep.target) } + Dep.target = _target + } + + function popTarget () { + Dep.target = targetStack.pop() + } + + /* */ + + + var queue = [] + var has$1 = {} + var circular = {} + var waiting = false + var flushing = false + var index = 0 + + /** + * Reset the scheduler's state. + */ + function resetSchedulerState () { + queue.length = 0 + has$1 = {} + { + circular = {} + } + waiting = flushing = false + } + + /** + * Flush both queues and run the watchers. + */ + function flushSchedulerQueue () { + flushing = true + + // Sort queue before flush. + // This ensures that: + // 1. Components are updated from parent to child. (because parent is always + // created before the child) + // 2. A component's user watchers are run before its render watcher (because + // user watchers are created before the render watcher) + // 3. If a component is destroyed during a parent component's watcher run, + // its watchers can be skipped. + queue.sort(function (a, b) { return a.id - b.id; }) + + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (index = 0; index < queue.length; index++) { + var watcher = queue[index] + var id = watcher.id + has$1[id] = null + watcher.run() + // in dev build, check and stop circular updates. + if ("development" !== 'production' && has$1[id] != null) { + circular[id] = (circular[id] || 0) + 1 + if (circular[id] > config._maxUpdateCount) { + warn( + 'You may have an infinite update loop ' + ( + watcher.user + ? ("in watcher with expression \"" + (watcher.expression) + "\"") + : "in a component render function." + ), + watcher.vm + ) + break + } + } + } + + // devtool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush') + } + + resetSchedulerState() + } + + /** + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. + */ + function queueWatcher (watcher) { + var id = watcher.id + if (has$1[id] == null) { + has$1[id] = true + if (!flushing) { + queue.push(watcher) + } else { + // if already flushing, splice the watcher based on its id + // if already past its id, it will be run next immediately. + var i = queue.length - 1 + while (i >= 0 && queue[i].id > watcher.id) { + i-- + } + queue.splice(Math.max(i, index) + 1, 0, watcher) + } + // queue the flush + if (!waiting) { + waiting = true + nextTick(flushSchedulerQueue) + } + } + } + + /* */ + + var uid$1 = 0 + + /** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + */ + var Watcher = function Watcher ( + vm, + expOrFn, + cb, + options + ) { + if ( options === void 0 ) options = {}; + + this.vm = vm + vm._watchers.push(this) + // options + this.deep = !!options.deep + this.user = !!options.user + this.lazy = !!options.lazy + this.sync = !!options.sync + this.expression = expOrFn.toString() + this.cb = cb + this.id = ++uid$1 // uid for batching + this.active = true + this.dirty = this.lazy // for lazy watchers + this.deps = [] + this.newDeps = [] + this.depIds = new _Set() + this.newDepIds = new _Set() + // parse expression for getter + if (typeof expOrFn === 'function') { + this.getter = expOrFn + } else { + this.getter = parsePath(expOrFn) + if (!this.getter) { + this.getter = function () {} + "development" !== 'production' && warn( + "Failed watching path: \"" + expOrFn + "\" " + + 'Watcher only accepts simple dot-delimited paths. ' + + 'For full control, use a function instead.', + vm + ) + } + } + this.value = this.lazy + ? undefined + : this.get() + }; + + /** + * Evaluate the getter, and re-collect dependencies. + */ + Watcher.prototype.get = function get () { + pushTarget(this) + var value = this.getter.call(this.vm, this.vm) + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value) + } + popTarget() + this.cleanupDeps() + return value + }; + + /** + * Add a dependency to this directive. + */ + Watcher.prototype.addDep = function addDep (dep) { + var id = dep.id + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id) + this.newDeps.push(dep) + if (!this.depIds.has(id)) { + dep.addSub(this) + } + } + }; + + /** + * Clean up for dependency collection. + */ + Watcher.prototype.cleanupDeps = function cleanupDeps () { + var this$1 = this; + + var i = this.deps.length + while (i--) { + var dep = this$1.deps[i] + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1) + } + } + var tmp = this.depIds + this.depIds = this.newDepIds + this.newDepIds = tmp + this.newDepIds.clear() + tmp = this.deps + this.deps = this.newDeps + this.newDeps = tmp + this.newDeps.length = 0 + }; + + /** + * Subscriber interface. + * Will be called when a dependency changes. + */ + Watcher.prototype.update = function update () { + /* istanbul ignore else */ + if (this.lazy) { + this.dirty = true + } else if (this.sync) { + this.run() + } else { + queueWatcher(this) + } + }; + + /** + * Scheduler job interface. + * Will be called by the scheduler. + */ + Watcher.prototype.run = function run () { + if (this.active) { + var value = this.get() + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + isObject(value) || + this.deep + ) { + // set new value + var oldValue = this.value + this.value = value + if (this.user) { + try { + this.cb.call(this.vm, value, oldValue) + } catch (e) { + "development" !== 'production' && warn( + ("Error in watcher \"" + (this.expression) + "\""), + this.vm + ) + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, this.vm) + } else { + throw e + } + } + } else { + this.cb.call(this.vm, value, oldValue) + } + } + } + }; + + /** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ + Watcher.prototype.evaluate = function evaluate () { + this.value = this.get() + this.dirty = false + }; + + /** + * Depend on all deps collected by this watcher. + */ + Watcher.prototype.depend = function depend () { + var this$1 = this; + + var i = this.deps.length + while (i--) { + this$1.deps[i].depend() + } + }; + + /** + * Remove self from all dependencies' subcriber list. + */ + Watcher.prototype.teardown = function teardown () { + var this$1 = this; + + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + remove$1(this.vm._watchers, this) + } + var i = this.deps.length + while (i--) { + this$1.deps[i].removeSub(this$1) + } + this.active = false + } + }; + + /** + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + */ + var seenObjects = new _Set() + function traverse (val, seen) { + var i, keys + if (!seen) { + seen = seenObjects + seen.clear() + } + var isA = Array.isArray(val) + var isO = isObject(val) + if ((isA || isO) && Object.isExtensible(val)) { + if (val.__ob__) { + var depId = val.__ob__.dep.id + if (seen.has(depId)) { + return + } else { + seen.add(depId) + } + } + if (isA) { + i = val.length + while (i--) { traverse(val[i], seen) } + } else if (isO) { + keys = Object.keys(val) + i = keys.length + while (i--) { traverse(val[keys[i]], seen) } + } + } + } + + /* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype + */ + + var arrayProto = Array.prototype + var arrayMethods = Object.create(arrayProto);[ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' + ] + .forEach(function (method) { + // cache original method + var original = arrayProto[method] + def(arrayMethods, method, function mutator () { + var arguments$1 = arguments; + + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length + var args = new Array(i) + while (i--) { + args[i] = arguments$1[i] + } + var result = original.apply(this, args) + var ob = this.__ob__ + var inserted + switch (method) { + case 'push': + inserted = args + break + case 'unshift': + inserted = args + break + case 'splice': + inserted = args.slice(2) + break + } + if (inserted) { ob.observeArray(inserted) } + // notify change + ob.dep.notify() + return result + }) + }) + + /* */ + + var arrayKeys = Object.getOwnPropertyNames(arrayMethods) + + /** + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However when passing down props, + * we don't want to force conversion because the value may be a nested value + * under a frozen data structure. Converting it would defeat the optimization. + */ + var observerState = { + shouldConvert: true, + isSettingProps: false + } + + /** + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. + */ + var Observer = function Observer (value) { + this.value = value + this.dep = new Dep() + this.vmCount = 0 + def(value, '__ob__', this) + if (Array.isArray(value)) { + var augment = hasProto + ? protoAugment + : copyAugment + augment(value, arrayMethods, arrayKeys) + this.observeArray(value) + } else { + this.walk(value) + } + }; + + /** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + */ + Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj) + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i], obj[keys[i]]) + } + }; + + /** + * Observe a list of Array items. + */ + Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]) + } + }; + + // helpers + + /** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + */ + function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src + /* eslint-enable no-proto */ + } + + /** + * Augment an target Object or Array by defining + * hidden properties. + * + * istanbul ignore next + */ + function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i] + def(target, key, src[key]) + } + } + + /** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + */ + function observe (value) { + if (!isObject(value)) { + return + } + var ob + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__ + } else if ( + observerState.shouldConvert && + !config._isServer && + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value) + } + return ob + } + + /** + * Define a reactive property on an Object. + */ + function defineReactive$$1 ( + obj, + key, + val, + customSetter + ) { + var dep = new Dep() + + var property = Object.getOwnPropertyDescriptor(obj, key) + if (property && property.configurable === false) { + return + } + + // cater for pre-defined getter/setters + var getter = property && property.get + var setter = property && property.set + + var childOb = observe(val) + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter () { + var value = getter ? getter.call(obj) : val + if (Dep.target) { + dep.depend() + if (childOb) { + childOb.dep.depend() + } + if (Array.isArray(value)) { + for (var e = void 0, i = 0, l = value.length; i < l; i++) { + e = value[i] + e && e.__ob__ && e.__ob__.dep.depend() + } + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val + if (newVal === value) { + return + } + if ("development" !== 'production' && customSetter) { + customSetter() + } + if (setter) { + setter.call(obj, newVal) + } else { + val = newVal + } + childOb = observe(newVal) + dep.notify() + } + }) + } + + /** + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. + */ + function set (obj, key, val) { + if (Array.isArray(obj)) { + obj.splice(key, 1, val) + return val + } + if (hasOwn(obj, key)) { + obj[key] = val + return + } + var ob = obj.__ob__ + if (obj._isVue || (ob && ob.vmCount)) { + "development" !== 'production' && warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ) + return + } + if (!ob) { + obj[key] = val + return + } + defineReactive$$1(ob.value, key, val) + ob.dep.notify() + return val + } + + /** + * Delete a property and trigger change if necessary. + */ + function del (obj, key) { + var ob = obj.__ob__ + if (obj._isVue || (ob && ob.vmCount)) { + "development" !== 'production' && warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ) + return + } + if (!hasOwn(obj, key)) { + return + } + delete obj[key] + if (!ob) { + return + } + ob.dep.notify() + } + + /* */ + + function initState (vm) { + vm._watchers = [] + initProps(vm) + initData(vm) + initComputed(vm) + initMethods(vm) + initWatch(vm) + } + + function initProps (vm) { + var props = vm.$options.props + if (props) { + var propsData = vm.$options.propsData || {} + var keys = vm.$options._propKeys = Object.keys(props) + var isRoot = !vm.$parent + // root instance props should be converted + observerState.shouldConvert = isRoot + var loop = function ( i ) { + var key = keys[i] + /* istanbul ignore else */ + { + defineReactive$$1(vm, key, validateProp(key, props, propsData, vm), function () { + if (vm.$parent && !observerState.isSettingProps) { + warn( + "Avoid mutating a prop directly since the value will be " + + "overwritten whenever the parent component re-renders. " + + "Instead, use a data or computed property based on the prop's " + + "value. Prop being mutated: \"" + key + "\"", + vm + ) + } + }) + } + }; + + for (var i = 0; i < keys.length; i++) loop( i ); + observerState.shouldConvert = true + } + } + + function initData (vm) { + var data = vm.$options.data + data = vm._data = typeof data === 'function' + ? data.call(vm) + : data || {} + if (!isPlainObject(data)) { + data = {} + "development" !== 'production' && warn( + 'data functions should return an object.', + vm + ) + } + // proxy data on instance + var keys = Object.keys(data) + var props = vm.$options.props + var i = keys.length + while (i--) { + if (props && hasOwn(props, keys[i])) { + "development" !== 'production' && warn( + "The data property \"" + (keys[i]) + "\" is already declared as a prop. " + + "Use prop default value instead.", + vm + ) + } else { + proxy(vm, keys[i]) + } + } + // observe data + observe(data) + data.__ob__ && data.__ob__.vmCount++ + } + + var computedSharedDefinition = { + enumerable: true, + configurable: true, + get: noop, + set: noop + } + + function initComputed (vm) { + var computed = vm.$options.computed + if (computed) { + for (var key in computed) { + var userDef = computed[key] + if (typeof userDef === 'function') { + computedSharedDefinition.get = makeComputedGetter(userDef, vm) + computedSharedDefinition.set = noop + } else { + computedSharedDefinition.get = userDef.get + ? userDef.cache !== false + ? makeComputedGetter(userDef.get, vm) + : bind$1(userDef.get, vm) + : noop + computedSharedDefinition.set = userDef.set + ? bind$1(userDef.set, vm) + : noop + } + Object.defineProperty(vm, key, computedSharedDefinition) + } + } + } + + function makeComputedGetter (getter, owner) { + var watcher = new Watcher(owner, getter, noop, { + lazy: true + }) + return function computedGetter () { + if (watcher.dirty) { + watcher.evaluate() + } + if (Dep.target) { + watcher.depend() + } + return watcher.value + } + } + + function initMethods (vm) { + var methods = vm.$options.methods + if (methods) { + for (var key in methods) { + if (methods[key] != null) { + vm[key] = bind$1(methods[key], vm) + } else { + warn(("Method \"" + key + "\" is undefined in options."), vm) + } + } + } + } + + function initWatch (vm) { + var watch = vm.$options.watch + if (watch) { + for (var key in watch) { + var handler = watch[key] + if (Array.isArray(handler)) { + for (var i = 0; i < handler.length; i++) { + createWatcher(vm, key, handler[i]) + } + } else { + createWatcher(vm, key, handler) + } + } + } + } + + function createWatcher (vm, key, handler) { + var options + if (isPlainObject(handler)) { + options = handler + handler = handler.handler + } + if (typeof handler === 'string') { + handler = vm[handler] + } + vm.$watch(key, handler, options) + } + + function stateMixin (Vue) { + // flow somehow has problems with directly declared definition object + // when using Object.defineProperty, so we have to procedurally build up + // the object here. + var dataDef = {} + dataDef.get = function () { + return this._data + } + { + dataDef.set = function (newData) { + warn( + 'Avoid replacing instance root $data. ' + + 'Use nested data properties instead.', + this + ) + } + } + Object.defineProperty(Vue.prototype, '$data', dataDef) + + Vue.prototype.$set = set + Vue.prototype.$delete = del + + Vue.prototype.$watch = function ( + expOrFn, + cb, + options + ) { + var vm = this + options = options || {} + options.user = true + var watcher = new Watcher(vm, expOrFn, cb, options) + if (options.immediate) { + cb.call(vm, watcher.value) + } + return function unwatchFn () { + watcher.teardown() + } + } + } + + function proxy (vm, key) { + if (!isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val + } + }) + } + } + + /* */ + + var VNode = function VNode ( + tag, + data, + children, + text, + elm, + ns, + context, + componentOptions + ) { + this.tag = tag + this.data = data + this.children = children + this.text = text + this.elm = elm + this.ns = ns + this.context = context + this.key = data && data.key + this.componentOptions = componentOptions + this.child = undefined + this.parent = undefined + this.raw = false + this.isStatic = false + this.isRootInsert = true + this.isComment = false + this.isCloned = false + }; + + var emptyVNode = function () { + var node = new VNode() + node.text = '' + node.isComment = true + return node + } + + // optimized shallow clone + // used for static nodes and slot nodes because they may be reused across + // multiple renders, cloning them avoids errors when DOM manipulations rely + // on their elm reference. + function cloneVNode (vnode) { + var cloned = new VNode( + vnode.tag, + vnode.data, + vnode.children, + vnode.text, + vnode.elm, + vnode.ns, + vnode.context, + vnode.componentOptions + ) + cloned.isStatic = vnode.isStatic + cloned.key = vnode.key + cloned.isCloned = true + return cloned + } + + function cloneVNodes (vnodes) { + var res = new Array(vnodes.length) + for (var i = 0; i < vnodes.length; i++) { + res[i] = cloneVNode(vnodes[i]) + } + return res + } + + /* */ + + function normalizeChildren ( + children, + ns, + nestedIndex + ) { + if (isPrimitive(children)) { + return [createTextVNode(children)] + } + if (Array.isArray(children)) { + var res = [] + for (var i = 0, l = children.length; i < l; i++) { + var c = children[i] + var last = res[res.length - 1] + // nested + if (Array.isArray(c)) { + res.push.apply(res, normalizeChildren(c, ns, i)) + } else if (isPrimitive(c)) { + if (last && last.text) { + last.text += String(c) + } else if (c !== '') { + // convert primitive to vnode + res.push(createTextVNode(c)) + } + } else if (c instanceof VNode) { + if (c.text && last && last.text) { + last.text += c.text + } else { + // inherit parent namespace + if (ns) { + applyNS(c, ns) + } + // default key for nested array children (likely generated by v-for) + if (c.tag && c.key == null && nestedIndex != null) { + c.key = "__vlist_" + nestedIndex + "_" + i + "__" + } + res.push(c) + } + } + } + return res + } + } + + function createTextVNode (val) { + return new VNode(undefined, undefined, undefined, String(val)) + } + + function applyNS (vnode, ns) { + if (vnode.tag && !vnode.ns) { + vnode.ns = ns + if (vnode.children) { + for (var i = 0, l = vnode.children.length; i < l; i++) { + applyNS(vnode.children[i], ns) + } + } + } + } + + function getFirstComponentChild (children) { + return children && children.filter(function (c) { return c && c.componentOptions; })[0] + } + + function mergeVNodeHook (def$$1, key, hook) { + var oldHook = def$$1[key] + if (oldHook) { + var injectedHash = def$$1.__injected || (def$$1.__injected = {}) + if (!injectedHash[key]) { + injectedHash[key] = true + def$$1[key] = function () { + oldHook.apply(this, arguments) + hook.apply(this, arguments) + } + } + } else { + def$$1[key] = hook + } + } + + function updateListeners ( + on, + oldOn, + add, + remove$$1 + ) { + var name, cur, old, fn, event, capture + for (name in on) { + cur = on[name] + old = oldOn[name] + if (!cur) { + "development" !== 'production' && warn( + ("Handler for event \"" + name + "\" is undefined.") + ) + } else if (!old) { + capture = name.charAt(0) === '!' + event = capture ? name.slice(1) : name + if (Array.isArray(cur)) { + add(event, (cur.invoker = arrInvoker(cur)), capture) + } else { + if (!cur.invoker) { + fn = cur + cur = on[name] = {} + cur.fn = fn + cur.invoker = fnInvoker(cur) + } + add(event, cur.invoker, capture) + } + } else if (cur !== old) { + if (Array.isArray(old)) { + old.length = cur.length + for (var i = 0; i < old.length; i++) { old[i] = cur[i] } + on[name] = old + } else { + old.fn = cur + on[name] = old + } + } + } + for (name in oldOn) { + if (!on[name]) { + event = name.charAt(0) === '!' ? name.slice(1) : name + remove$$1(event, oldOn[name].invoker) + } + } + } + + function arrInvoker (arr) { + return function (ev) { + var arguments$1 = arguments; + + var single = arguments.length === 1 + for (var i = 0; i < arr.length; i++) { + single ? arr[i](ev) : arr[i].apply(null, arguments$1) + } + } + } + + function fnInvoker (o) { + return function (ev) { + var single = arguments.length === 1 + single ? o.fn(ev) : o.fn.apply(null, arguments) + } + } + + /* */ + + var activeInstance = null + + function initLifecycle (vm) { + var options = vm.$options + + // locate first non-abstract parent + var parent = options.parent + if (parent && !options.abstract) { + while (parent.$options.abstract && parent.$parent) { + parent = parent.$parent + } + parent.$children.push(vm) + } + + vm.$parent = parent + vm.$root = parent ? parent.$root : vm + + vm.$children = [] + vm.$refs = {} + + vm._watcher = null + vm._inactive = false + vm._isMounted = false + vm._isDestroyed = false + vm._isBeingDestroyed = false + } + + function lifecycleMixin (Vue) { + Vue.prototype._mount = function ( + el, + hydrating + ) { + var vm = this + vm.$el = el + if (!vm.$options.render) { + vm.$options.render = emptyVNode + { + /* istanbul ignore if */ + if (vm.$options.template) { + warn( + 'You are using the runtime-only build of Vue where the template ' + + 'option is not available. Either pre-compile the templates into ' + + 'render functions, or use the compiler-included build.', + vm + ) + } else { + warn( + 'Failed to mount component: template or render function not defined.', + vm + ) + } + } + } + callHook(vm, 'beforeMount') + vm._watcher = new Watcher(vm, function () { + vm._update(vm._render(), hydrating) + }, noop) + hydrating = false + // root instance, call mounted on self + // mounted is called for child components in its inserted hook + if (vm.$root === vm) { + vm._isMounted = true + callHook(vm, 'mounted') + } + return vm + } + + Vue.prototype._update = function (vnode, hydrating) { + var vm = this + if (vm._isMounted) { + callHook(vm, 'beforeUpdate') + } + var prevEl = vm.$el + var prevActiveInstance = activeInstance + activeInstance = vm + var prevVnode = vm._vnode + vm._vnode = vnode + if (!prevVnode) { + // Vue.prototype.__patch__ is injected in entry points + // based on the rendering backend used. + vm.$el = vm.__patch__(vm.$el, vnode, hydrating) + } else { + vm.$el = vm.__patch__(prevVnode, vnode) + } + activeInstance = prevActiveInstance + // update __vue__ reference + if (prevEl) { + prevEl.__vue__ = null + } + if (vm.$el) { + vm.$el.__vue__ = vm + } + // if parent is an HOC, update its $el as well + if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) { + vm.$parent.$el = vm.$el + } + if (vm._isMounted) { + callHook(vm, 'updated') + } + } + + Vue.prototype._updateFromParent = function ( + propsData, + listeners, + parentVnode, + renderChildren + ) { + var vm = this + var hasChildren = !!(vm.$options._renderChildren || renderChildren) + vm.$options._parentVnode = parentVnode + vm.$options._renderChildren = renderChildren + // update props + if (propsData && vm.$options.props) { + observerState.shouldConvert = false + { + observerState.isSettingProps = true + } + var propKeys = vm.$options._propKeys || [] + for (var i = 0; i < propKeys.length; i++) { + var key = propKeys[i] + vm[key] = validateProp(key, vm.$options.props, propsData, vm) + } + observerState.shouldConvert = true + { + observerState.isSettingProps = false + } + } + // update listeners + if (listeners) { + var oldListeners = vm.$options._parentListeners + vm.$options._parentListeners = listeners + vm._updateListeners(listeners, oldListeners) + } + // resolve slots + force update if has children + if (hasChildren) { + vm.$slots = resolveSlots(renderChildren, vm._renderContext) + vm.$forceUpdate() + } + } + + Vue.prototype.$forceUpdate = function () { + var vm = this + if (vm._watcher) { + vm._watcher.update() + } + } + + Vue.prototype.$destroy = function () { + var vm = this + if (vm._isBeingDestroyed) { + return + } + callHook(vm, 'beforeDestroy') + vm._isBeingDestroyed = true + // remove self from parent + var parent = vm.$parent + if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) { + remove$1(parent.$children, vm) + } + // teardown watchers + if (vm._watcher) { + vm._watcher.teardown() + } + var i = vm._watchers.length + while (i--) { + vm._watchers[i].teardown() + } + // remove reference from data ob + // frozen object may not have observer. + if (vm._data.__ob__) { + vm._data.__ob__.vmCount-- + } + // call the last hook... + vm._isDestroyed = true + callHook(vm, 'destroyed') + // turn off all instance listeners. + vm.$off() + // remove __vue__ reference + if (vm.$el) { + vm.$el.__vue__ = null + } + } + } + + function callHook (vm, hook) { + var handlers = vm.$options[hook] + if (handlers) { + for (var i = 0, j = handlers.length; i < j; i++) { + handlers[i].call(vm) + } + } + vm.$emit('hook:' + hook) + } + + /* */ + + var hooks = { init: init, prepatch: prepatch, insert: insert, destroy: destroy$1 } + var hooksToMerge = Object.keys(hooks) + + function createComponent ( + Ctor, + data, + context, + children, + tag + ) { + if (!Ctor) { + return + } + + if (isObject(Ctor)) { + Ctor = Vue$3.extend(Ctor) + } + + if (typeof Ctor !== 'function') { + { + warn(("Invalid Component definition: " + (String(Ctor))), context) + } + return + } + + // async component + if (!Ctor.cid) { + if (Ctor.resolved) { + Ctor = Ctor.resolved + } else { + Ctor = resolveAsyncComponent(Ctor, function () { + // it's ok to queue this on every render because + // $forceUpdate is buffered by the scheduler. + context.$forceUpdate() + }) + if (!Ctor) { + // return nothing if this is indeed an async component + // wait for the callback to trigger parent update. + return + } + } + } + + data = data || {} + + // extract props + var propsData = extractProps(data, Ctor) + + // functional component + if (Ctor.options.functional) { + return createFunctionalComponent(Ctor, propsData, data, context, children) + } + + // extract listeners, since these needs to be treated as + // child component listeners instead of DOM listeners + var listeners = data.on + // replace with listeners with .native modifier + data.on = data.nativeOn + + if (Ctor.options.abstract) { + // abstract components do not keep anything + // other than props & listeners + data = {} + } + + // merge component management hooks onto the placeholder node + mergeHooks(data) + + // return a placeholder vnode + var name = Ctor.options.name || tag + var vnode = new VNode( + ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')), + data, undefined, undefined, undefined, undefined, context, + { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children } + ) + return vnode + } + + function createFunctionalComponent ( + Ctor, + propsData, + data, + context, + children + ) { + var props = {} + var propOptions = Ctor.options.props + if (propOptions) { + for (var key in propOptions) { + props[key] = validateProp(key, propOptions, propsData) + } + } + return Ctor.options.render.call( + null, + // ensure the createElement function in functional components + // gets a unique context - this is necessary for correct named slot check + bind$1(createElement, { _self: Object.create(context) }), + { + props: props, + data: data, + parent: context, + children: normalizeChildren(children), + slots: function () { return resolveSlots(children, context); } + } + ) + } + + function createComponentInstanceForVnode ( + vnode, // we know it's MountedComponentVNode but flow doesn't + parent // activeInstance in lifecycle state + ) { + var vnodeComponentOptions = vnode.componentOptions + var options = { + _isComponent: true, + parent: parent, + propsData: vnodeComponentOptions.propsData, + _componentTag: vnodeComponentOptions.tag, + _parentVnode: vnode, + _parentListeners: vnodeComponentOptions.listeners, + _renderChildren: vnodeComponentOptions.children + } + // check inline-template render functions + var inlineTemplate = vnode.data.inlineTemplate + if (inlineTemplate) { + options.render = inlineTemplate.render + options.staticRenderFns = inlineTemplate.staticRenderFns + } + return new vnodeComponentOptions.Ctor(options) + } + + function init (vnode, hydrating) { + if (!vnode.child || vnode.child._isDestroyed) { + var child = vnode.child = createComponentInstanceForVnode(vnode, activeInstance) + child.$mount(hydrating ? vnode.elm : undefined, hydrating) + } + } + + function prepatch ( + oldVnode, + vnode + ) { + var options = vnode.componentOptions + var child = vnode.child = oldVnode.child + child._updateFromParent( + options.propsData, // updated props + options.listeners, // updated listeners + vnode, // new parent vnode + options.children // new children + ) + } + + function insert (vnode) { + if (!vnode.child._isMounted) { + vnode.child._isMounted = true + callHook(vnode.child, 'mounted') + } + if (vnode.data.keepAlive) { + vnode.child._inactive = false + callHook(vnode.child, 'activated') + } + } + + function destroy$1 (vnode) { + if (!vnode.child._isDestroyed) { + if (!vnode.data.keepAlive) { + vnode.child.$destroy() + } else { + vnode.child._inactive = true + callHook(vnode.child, 'deactivated') + } + } + } + + function resolveAsyncComponent ( + factory, + cb + ) { + if (factory.requested) { + // pool callbacks + factory.pendingCallbacks.push(cb) + } else { + factory.requested = true + var cbs = factory.pendingCallbacks = [cb] + var sync = true + + var resolve = function (res) { + if (isObject(res)) { + res = Vue$3.extend(res) + } + // cache resolved + factory.resolved = res + // invoke callbacks only if this is not a synchronous resolve + // (async resolves are shimmed as synchronous during SSR) + if (!sync) { + for (var i = 0, l = cbs.length; i < l; i++) { + cbs[i](res) + } + } + } + + var reject = function (reason) { + "development" !== 'production' && warn( + "Failed to resolve async component: " + (String(factory)) + + (reason ? ("\nReason: " + reason) : '') + ) + } + + var res = factory(resolve, reject) + + // handle promise + if (res && typeof res.then === 'function' && !factory.resolved) { + res.then(resolve, reject) + } + + sync = false + // return in case resolved synchronously + return factory.resolved + } + } + + function extractProps (data, Ctor) { + // we are only extrating raw values here. + // validation and default values are handled in the child + // component itself. + var propOptions = Ctor.options.props + if (!propOptions) { + return + } + var res = {} + var attrs = data.attrs; + var props = data.props; + var domProps = data.domProps; + if (attrs || props || domProps) { + for (var key in propOptions) { + var altKey = hyphenate(key) + checkProp(res, props, key, altKey, true) || + checkProp(res, attrs, key, altKey) || + checkProp(res, domProps, key, altKey) + } + } + return res + } + + function checkProp ( + res, + hash, + key, + altKey, + preserve + ) { + if (hash) { + if (hasOwn(hash, key)) { + res[key] = hash[key] + if (!preserve) { + delete hash[key] + } + return true + } else if (hasOwn(hash, altKey)) { + res[key] = hash[altKey] + if (!preserve) { + delete hash[altKey] + } + return true + } + } + return false + } + + function mergeHooks (data) { + if (!data.hook) { + data.hook = {} + } + for (var i = 0; i < hooksToMerge.length; i++) { + var key = hooksToMerge[i] + var fromParent = data.hook[key] + var ours = hooks[key] + data.hook[key] = fromParent ? mergeHook$1(ours, fromParent) : ours + } + } + + function mergeHook$1 (a, b) { + // since all hooks have at most two args, use fixed args + // to avoid having to use fn.apply(). + return function (_, __) { + a(_, __) + b(_, __) + } + } + + /* */ + + // wrapper function for providing a more flexible interface + // without getting yelled at by flow + function createElement ( + tag, + data, + children + ) { + if (data && (Array.isArray(data) || typeof data !== 'object')) { + children = data + data = undefined + } + // make sure to use real instance instead of proxy as context + return _createElement(this._self, tag, data, children) + } + + function _createElement ( + context, + tag, + data, + children + ) { + if (data && data.__ob__) { + "development" !== 'production' && warn( + "Avoid using observed data object as vnode data: " + (JSON.stringify(data)) + "\n" + + 'Always create fresh vnode data objects in each render!', + context + ) + return + } + if (!tag) { + // in case of component :is set to falsy value + return emptyVNode() + } + if (typeof tag === 'string') { + var Ctor + var ns = config.getTagNamespace(tag) + if (config.isReservedTag(tag)) { + // platform built-in elements + return new VNode( + tag, data, normalizeChildren(children, ns), + undefined, undefined, ns, context + ) + } else if ((Ctor = resolveAsset(context.$options, 'components', tag))) { + // component + return createComponent(Ctor, data, context, children, tag) + } else { + // unknown or unlisted namespaced elements + // check at runtime because it may get assigned a namespace when its + // parent normalizes children + return new VNode( + tag, data, normalizeChildren(children, ns), + undefined, undefined, ns, context + ) + } + } else { + // direct component options / constructor + return createComponent(tag, data, context, children) + } + } + + /* */ + + function initRender (vm) { + vm.$vnode = null // the placeholder node in parent tree + vm._vnode = null // the root of the child tree + vm._staticTrees = null + vm._renderContext = vm.$options._parentVnode && vm.$options._parentVnode.context + vm.$slots = resolveSlots(vm.$options._renderChildren, vm._renderContext) + // bind the public createElement fn to this instance + // so that we get proper render context inside it. + vm.$createElement = bind$1(createElement, vm) + if (vm.$options.el) { + vm.$mount(vm.$options.el) + } + } + + function renderMixin (Vue) { + Vue.prototype.$nextTick = function (fn) { + nextTick(fn, this) + } + + Vue.prototype._render = function () { + var vm = this + var ref = vm.$options; + var render = ref.render; + var staticRenderFns = ref.staticRenderFns; + var _parentVnode = ref._parentVnode; + + if (vm._isMounted) { + // clone slot nodes on re-renders + for (var key in vm.$slots) { + vm.$slots[key] = cloneVNodes(vm.$slots[key]) + } + } + + if (staticRenderFns && !vm._staticTrees) { + vm._staticTrees = [] + } + // set parent vnode. this allows render functions to have access + // to the data on the placeholder node. + vm.$vnode = _parentVnode + // render self + var vnode + try { + vnode = render.call(vm._renderProxy, vm.$createElement) + } catch (e) { + { + warn(("Error when rendering " + (formatComponentName(vm)) + ":")) + } + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, vm) + } else { + if (config._isServer) { + throw e + } else { + setTimeout(function () { throw e }, 0) + } + } + // return previous vnode to prevent render error causing blank component + vnode = vm._vnode + } + // return empty vnode in case the render function errored out + if (!(vnode instanceof VNode)) { + if ("development" !== 'production' && Array.isArray(vnode)) { + warn( + 'Multiple root nodes returned from render function. Render function ' + + 'should return a single root node.', + vm + ) + } + vnode = emptyVNode() + } + // set parent + vnode.parent = _parentVnode + return vnode + } + + // shorthands used in render functions + Vue.prototype._h = createElement + // toString for mustaches + Vue.prototype._s = _toString + // number conversion + Vue.prototype._n = toNumber + // empty vnode + Vue.prototype._e = emptyVNode + // loose equal + Vue.prototype._q = looseEqual + // loose indexOf + Vue.prototype._i = looseIndexOf + + // render static tree by index + Vue.prototype._m = function renderStatic ( + index, + isInFor + ) { + var tree = this._staticTrees[index] + // if has already-rendered static tree and not inside v-for, + // we can reuse the same tree by doing a shallow clone. + if (tree && !isInFor) { + return Array.isArray(tree) + ? cloneVNodes(tree) + : cloneVNode(tree) + } + // otherwise, render a fresh tree. + tree = this._staticTrees[index] = this.$options.staticRenderFns[index].call(this._renderProxy) + if (Array.isArray(tree)) { + for (var i = 0; i < tree.length; i++) { + tree[i].isStatic = true + tree[i].key = "__static__" + index + "_" + i + } + } else { + tree.isStatic = true + tree.key = "__static__" + index + } + return tree + } + + // filter resolution helper + var identity = function (_) { return _; } + Vue.prototype._f = function resolveFilter (id) { + return resolveAsset(this.$options, 'filters', id, true) || identity + } + + // render v-for + Vue.prototype._l = function renderList ( + val, + render + ) { + var ret, i, l, keys, key + if (Array.isArray(val)) { + ret = new Array(val.length) + for (i = 0, l = val.length; i < l; i++) { + ret[i] = render(val[i], i) + } + } else if (typeof val === 'number') { + ret = new Array(val) + for (i = 0; i < val; i++) { + ret[i] = render(i + 1, i) + } + } else if (isObject(val)) { + keys = Object.keys(val) + ret = new Array(keys.length) + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i] + ret[i] = render(val[key], key, i) + } + } + return ret + } + + // renderSlot + Vue.prototype._t = function ( + name, + fallback + ) { + var slotNodes = this.$slots[name] + // warn duplicate slot usage + if (slotNodes && "development" !== 'production') { + slotNodes._rendered && warn( + "Duplicate presence of slot \"" + name + "\" found in the same render tree " + + "- this will likely cause render errors.", + this + ) + slotNodes._rendered = true + } + return slotNodes || fallback + } + + // apply v-bind object + Vue.prototype._b = function bindProps ( + data, + value, + asProp + ) { + if (value) { + if (!isObject(value)) { + "development" !== 'production' && warn( + 'v-bind without argument expects an Object or Array value', + this + ) + } else { + if (Array.isArray(value)) { + value = toObject(value) + } + for (var key in value) { + if (key === 'class' || key === 'style') { + data[key] = value[key] + } else { + var hash = asProp || config.mustUseProp(key) + ? data.domProps || (data.domProps = {}) + : data.attrs || (data.attrs = {}) + hash[key] = value[key] + } + } + } + } + return data + } + + // expose v-on keyCodes + Vue.prototype._k = function getKeyCodes (key) { + return config.keyCodes[key] + } + } + + function resolveSlots ( + renderChildren, + context + ) { + var slots = {} + if (!renderChildren) { + return slots + } + var children = normalizeChildren(renderChildren) || [] + var defaultSlot = [] + var name, child + for (var i = 0, l = children.length; i < l; i++) { + child = children[i] + // named slots should only be respected if the vnode was rendered in the + // same context. + if (child.context === context && + child.data && (name = child.data.slot)) { + var slot = (slots[name] || (slots[name] = [])) + if (child.tag === 'template') { + slot.push.apply(slot, child.children) + } else { + slot.push(child) + } + } else { + defaultSlot.push(child) + } + } + // ignore single whitespace + if (defaultSlot.length && !( + defaultSlot.length === 1 && + (defaultSlot[0].text === ' ' || defaultSlot[0].isComment) + )) { + slots.default = defaultSlot + } + return slots + } + + /* */ + + function initEvents (vm) { + vm._events = Object.create(null) + // init parent attached events + var listeners = vm.$options._parentListeners + var on = bind$1(vm.$on, vm) + var off = bind$1(vm.$off, vm) + vm._updateListeners = function (listeners, oldListeners) { + updateListeners(listeners, oldListeners || {}, on, off) + } + if (listeners) { + vm._updateListeners(listeners) + } + } + + function eventsMixin (Vue) { + Vue.prototype.$on = function (event, fn) { + var vm = this;(vm._events[event] || (vm._events[event] = [])).push(fn) + return vm + } + + Vue.prototype.$once = function (event, fn) { + var vm = this + function on () { + vm.$off(event, on) + fn.apply(vm, arguments) + } + on.fn = fn + vm.$on(event, on) + return vm + } + + Vue.prototype.$off = function (event, fn) { + var vm = this + // all + if (!arguments.length) { + vm._events = Object.create(null) + return vm + } + // specific event + var cbs = vm._events[event] + if (!cbs) { + return vm + } + if (arguments.length === 1) { + vm._events[event] = null + return vm + } + // specific handler + var cb + var i = cbs.length + while (i--) { + cb = cbs[i] + if (cb === fn || cb.fn === fn) { + cbs.splice(i, 1) + break + } + } + return vm + } + + Vue.prototype.$emit = function (event) { + var vm = this + var cbs = vm._events[event] + if (cbs) { + cbs = cbs.length > 1 ? toArray(cbs) : cbs + var args = toArray(arguments, 1) + for (var i = 0, l = cbs.length; i < l; i++) { + cbs[i].apply(vm, args) + } + } + return vm + } + } + + /* */ + + var uid = 0 + + function initMixin (Vue) { + Vue.prototype._init = function (options) { + var vm = this + // a uid + vm._uid = uid++ + // a flag to avoid this being observed + vm._isVue = true + // merge options + if (options && options._isComponent) { + // optimize internal component instantiation + // since dynamic options merging is pretty slow, and none of the + // internal component options needs special treatment. + initInternalComponent(vm, options) + } else { + vm.$options = mergeOptions( + resolveConstructorOptions(vm), + options || {}, + vm + ) + } + /* istanbul ignore else */ + { + initProxy(vm) + } + // expose real self + vm._self = vm + initLifecycle(vm) + initEvents(vm) + callHook(vm, 'beforeCreate') + initState(vm) + callHook(vm, 'created') + initRender(vm) + } + + function initInternalComponent (vm, options) { + var opts = vm.$options = Object.create(resolveConstructorOptions(vm)) + // doing this because it's faster than dynamic enumeration. + opts.parent = options.parent + opts.propsData = options.propsData + opts._parentVnode = options._parentVnode + opts._parentListeners = options._parentListeners + opts._renderChildren = options._renderChildren + opts._componentTag = options._componentTag + if (options.render) { + opts.render = options.render + opts.staticRenderFns = options.staticRenderFns + } + } + + function resolveConstructorOptions (vm) { + var Ctor = vm.constructor + var options = Ctor.options + if (Ctor.super) { + var superOptions = Ctor.super.options + var cachedSuperOptions = Ctor.superOptions + if (superOptions !== cachedSuperOptions) { + // super option changed + Ctor.superOptions = superOptions + options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions) + if (options.name) { + options.components[options.name] = Ctor + } + } + } + return options + } + } + + function Vue$3 (options) { + if ("development" !== 'production' && + !(this instanceof Vue$3)) { + warn('Vue is a constructor and should be called with the `new` keyword') + } + this._init(options) + } + + initMixin(Vue$3) + stateMixin(Vue$3) + eventsMixin(Vue$3) + lifecycleMixin(Vue$3) + renderMixin(Vue$3) + + var warn = noop + var formatComponentName + + { + var hasConsole = typeof console !== 'undefined' + + warn = function (msg, vm) { + if (hasConsole && (!config.silent)) { + console.error("[Vue warn]: " + msg + " " + ( + vm ? formatLocation(formatComponentName(vm)) : '' + )) + } + } + + formatComponentName = function (vm) { + if (vm.$root === vm) { + return 'root instance' + } + var name = vm._isVue + ? vm.$options.name || vm.$options._componentTag + : vm.name + return name ? ("component <" + name + ">") : "anonymous component" + } + + var formatLocation = function (str) { + if (str === 'anonymous component') { + str += " - use the \"name\" option for better debugging messages." + } + return ("(found in " + str + ")") + } + } + + /* */ + + /** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + */ + var strats = config.optionMergeStrategies + + /** + * Options with restrictions + */ + { + strats.el = strats.propsData = function (parent, child, vm, key) { + if (!vm) { + warn( + "option \"" + key + "\" can only be used during instance " + + 'creation with the `new` keyword.' + ) + } + return defaultStrat(parent, child) + } + + strats.name = function (parent, child, vm) { + if (vm && child) { + warn( + 'options "name" can only be used as a component definition option, ' + + 'not during instance creation.' + ) + } + return defaultStrat(parent, child) + } + } + + /** + * Helper that recursively merges two data objects together. + */ + function mergeData (to, from) { + var key, toVal, fromVal + for (key in from) { + toVal = to[key] + fromVal = from[key] + if (!hasOwn(to, key)) { + set(to, key, fromVal) + } else if (isObject(toVal) && isObject(fromVal)) { + mergeData(toVal, fromVal) + } + } + return to + } + + /** + * Data + */ + strats.data = function ( + parentVal, + childVal, + vm + ) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal + } + if (typeof childVal !== 'function') { + "development" !== 'production' && warn( + 'The "data" option should be a function ' + + 'that returns a per-instance value in component ' + + 'definitions.', + vm + ) + return parentVal + } + if (!parentVal) { + return childVal + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn () { + return mergeData( + childVal.call(this), + parentVal.call(this) + ) + } + } else if (parentVal || childVal) { + return function mergedInstanceDataFn () { + // instance merge + var instanceData = typeof childVal === 'function' + ? childVal.call(vm) + : childVal + var defaultData = typeof parentVal === 'function' + ? parentVal.call(vm) + : undefined + if (instanceData) { + return mergeData(instanceData, defaultData) + } else { + return defaultData + } + } + } + } + + /** + * Hooks and param attributes are merged as arrays. + */ + function mergeHook ( + parentVal, + childVal + ) { + return childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal + : [childVal] + : parentVal + } + + config._lifecycleHooks.forEach(function (hook) { + strats[hook] = mergeHook + }) + + /** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ + function mergeAssets (parentVal, childVal) { + var res = Object.create(parentVal || null) + return childVal + ? extend(res, childVal) + : res + } + + config._assetTypes.forEach(function (type) { + strats[type + 's'] = mergeAssets + }) + + /** + * Watchers. + * + * Watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ + strats.watch = function (parentVal, childVal) { + /* istanbul ignore if */ + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = {} + extend(ret, parentVal) + for (var key in childVal) { + var parent = ret[key] + var child = childVal[key] + if (parent && !Array.isArray(parent)) { + parent = [parent] + } + ret[key] = parent + ? parent.concat(child) + : [child] + } + return ret + } + + /** + * Other object hashes. + */ + strats.props = + strats.methods = + strats.computed = function (parentVal, childVal) { + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = Object.create(null) + extend(ret, parentVal) + extend(ret, childVal) + return ret + } + + /** + * Default strategy. + */ + var defaultStrat = function (parentVal, childVal) { + return childVal === undefined + ? parentVal + : childVal + } + + /** + * Make sure component options get converted to actual + * constructors. + */ + function normalizeComponents (options) { + if (options.components) { + var components = options.components + var def + for (var key in components) { + var lower = key.toLowerCase() + if (isBuiltInTag(lower) || config.isReservedTag(lower)) { + "development" !== 'production' && warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + key + ) + continue + } + def = components[key] + if (isPlainObject(def)) { + components[key] = Vue$3.extend(def) + } + } + } + } + + /** + * Ensure all props option syntax are normalized into the + * Object-based format. + */ + function normalizeProps (options) { + var props = options.props + if (!props) { return } + var res = {} + var i, val, name + if (Array.isArray(props)) { + i = props.length + while (i--) { + val = props[i] + if (typeof val === 'string') { + name = camelize(val) + res[name] = { type: null } + } else { + warn('props must be strings when using array syntax.') + } + } + } else if (isPlainObject(props)) { + for (var key in props) { + val = props[key] + name = camelize(key) + res[name] = isPlainObject(val) + ? val + : { type: val } + } + } + options.props = res + } + + /** + * Normalize raw function directives into object format. + */ + function normalizeDirectives (options) { + var dirs = options.directives + if (dirs) { + for (var key in dirs) { + var def = dirs[key] + if (typeof def === 'function') { + dirs[key] = { bind: def, update: def } + } + } + } + } + + /** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + */ + function mergeOptions ( + parent, + child, + vm + ) { + normalizeComponents(child) + normalizeProps(child) + normalizeDirectives(child) + var extendsFrom = child.extends + if (extendsFrom) { + parent = typeof extendsFrom === 'function' + ? mergeOptions(parent, extendsFrom.options, vm) + : mergeOptions(parent, extendsFrom, vm) + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + var mixin = child.mixins[i] + if (mixin.prototype instanceof Vue$3) { + mixin = mixin.options + } + parent = mergeOptions(parent, mixin, vm) + } + } + var options = {} + var key + for (key in parent) { + mergeField(key) + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key) + } + } + function mergeField (key) { + var strat = strats[key] || defaultStrat + options[key] = strat(parent[key], child[key], vm, key) + } + return options + } + + /** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + */ + function resolveAsset ( + options, + type, + id, + warnMissing + ) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return + } + var assets = options[type] + var res = assets[id] || + // camelCase ID + assets[camelize(id)] || + // Pascal Case ID + assets[capitalize(camelize(id))] + if ("development" !== 'production' && warnMissing && !res) { + warn( + 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, + options + ) + } + return res + } + + /* */ + + function validateProp ( + key, + propOptions, + propsData, + vm + ) { + var prop = propOptions[key] + var absent = !hasOwn(propsData, key) + var value = propsData[key] + // handle boolean props + if (getType(prop.type) === 'Boolean') { + if (absent && !hasOwn(prop, 'default')) { + value = false + } else if (value === '' || value === hyphenate(key)) { + value = true + } + } + // check default value + if (value === undefined) { + value = getPropDefaultValue(vm, prop, key) + // since the default value is a fresh copy, + // make sure to observe it. + var prevShouldConvert = observerState.shouldConvert + observerState.shouldConvert = true + observe(value) + observerState.shouldConvert = prevShouldConvert + } + { + assertProp(prop, key, value, vm, absent) + } + return value + } + + /** + * Get the default value of a prop. + */ + function getPropDefaultValue (vm, prop, name) { + // no default, return undefined + if (!hasOwn(prop, 'default')) { + return undefined + } + var def = prop.default + // warn against non-factory defaults for Object & Array + if (isObject(def)) { + "development" !== 'production' && warn( + 'Invalid default value for prop "' + name + '": ' + + 'Props with type Object/Array must use a factory function ' + + 'to return the default value.', + vm + ) + } + // call factory function for non-Function types + return typeof def === 'function' && prop.type !== Function + ? def.call(vm) + : def + } + + /** + * Assert whether a prop is valid. + */ + function assertProp ( + prop, + name, + value, + vm, + absent + ) { + if (prop.required && absent) { + warn( + 'Missing required prop: "' + name + '"', + vm + ) + return + } + if (value == null && !prop.required) { + return + } + var type = prop.type + var valid = !type || type === true + var expectedTypes = [] + if (type) { + if (!Array.isArray(type)) { + type = [type] + } + for (var i = 0; i < type.length && !valid; i++) { + var assertedType = assertType(value, type[i]) + expectedTypes.push(assertedType.expectedType) + valid = assertedType.valid + } + } + if (!valid) { + warn( + 'Invalid prop: type check failed for prop "' + name + '".' + + ' Expected ' + expectedTypes.map(capitalize).join(', ') + + ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.', + vm + ) + return + } + var validator = prop.validator + if (validator) { + if (!validator(value)) { + warn( + 'Invalid prop: custom validator check failed for prop "' + name + '".', + vm + ) + } + } + } + + /** + * Assert the type of a value + */ + function assertType (value, type) { + var valid + var expectedType = getType(type) + if (expectedType === 'String') { + valid = typeof value === (expectedType = 'string') + } else if (expectedType === 'Number') { + valid = typeof value === (expectedType = 'number') + } else if (expectedType === 'Boolean') { + valid = typeof value === (expectedType = 'boolean') + } else if (expectedType === 'Function') { + valid = typeof value === (expectedType = 'function') + } else if (expectedType === 'Object') { + valid = isPlainObject(value) + } else if (expectedType === 'Array') { + valid = Array.isArray(value) + } else { + valid = value instanceof type + } + return { + valid: valid, + expectedType: expectedType + } + } + + /** + * Use function string name to check built-in types, + * because a simple equality check will fail when running + * across different vms / iframes. + */ + function getType (fn) { + var match = fn && fn.toString().match(/^\s*function (\w+)/) + return match && match[1] + } + + + + var util = Object.freeze({ + defineReactive: defineReactive$$1, + _toString: _toString, + toNumber: toNumber, + makeMap: makeMap, + isBuiltInTag: isBuiltInTag, + remove: remove$1, + hasOwn: hasOwn, + isPrimitive: isPrimitive, + cached: cached, + camelize: camelize, + capitalize: capitalize, + hyphenate: hyphenate, + bind: bind$1, + toArray: toArray, + extend: extend, + isObject: isObject, + isPlainObject: isPlainObject, + toObject: toObject, + noop: noop, + no: no, + genStaticKeys: genStaticKeys, + looseEqual: looseEqual, + looseIndexOf: looseIndexOf, + isReserved: isReserved, + def: def, + parsePath: parsePath, + hasProto: hasProto, + inBrowser: inBrowser, + UA: UA, + isIE: isIE, + isIE9: isIE9, + isEdge: isEdge, + isAndroid: isAndroid, + isIOS: isIOS, + devtools: devtools, + nextTick: nextTick, + get _Set () { return _Set; }, + mergeOptions: mergeOptions, + resolveAsset: resolveAsset, + get warn () { return warn; }, + get formatComponentName () { return formatComponentName; }, + validateProp: validateProp + }); + + /* */ + + function initUse (Vue) { + Vue.use = function (plugin) { + /* istanbul ignore if */ + if (plugin.installed) { + return + } + // additional parameters + var args = toArray(arguments, 1) + args.unshift(this) + if (typeof plugin.install === 'function') { + plugin.install.apply(plugin, args) + } else { + plugin.apply(null, args) + } + plugin.installed = true + return this + } + } + + /* */ + + function initMixin$1 (Vue) { + Vue.mixin = function (mixin) { + Vue.options = mergeOptions(Vue.options, mixin) + } + } + + /* */ + + function initExtend (Vue) { + /** + * Each instance constructor, including Vue, has a unique + * cid. This enables us to create wrapped "child + * constructors" for prototypal inheritance and cache them. + */ + Vue.cid = 0 + var cid = 1 + + /** + * Class inheritance + */ + Vue.extend = function (extendOptions) { + extendOptions = extendOptions || {} + var Super = this + var isFirstExtend = Super.cid === 0 + if (isFirstExtend && extendOptions._Ctor) { + return extendOptions._Ctor + } + var name = extendOptions.name || Super.options.name + { + if (!/^[a-zA-Z][\w-]*$/.test(name)) { + warn( + 'Invalid component name: "' + name + '". Component names ' + + 'can only contain alphanumeric characaters and the hyphen.' + ) + name = null + } + } + var Sub = function VueComponent (options) { + this._init(options) + } + Sub.prototype = Object.create(Super.prototype) + Sub.prototype.constructor = Sub + Sub.cid = cid++ + Sub.options = mergeOptions( + Super.options, + extendOptions + ) + Sub['super'] = Super + // allow further extension + Sub.extend = Super.extend + // create asset registers, so extended classes + // can have their private assets too. + config._assetTypes.forEach(function (type) { + Sub[type] = Super[type] + }) + // enable recursive self-lookup + if (name) { + Sub.options.components[name] = Sub + } + // keep a reference to the super options at extension time. + // later at instantiation we can check if Super's options have + // been updated. + Sub.superOptions = Super.options + Sub.extendOptions = extendOptions + // cache constructor + if (isFirstExtend) { + extendOptions._Ctor = Sub + } + return Sub + } + } + + /* */ + + function initAssetRegisters (Vue) { + /** + * Create asset registration methods. + */ + config._assetTypes.forEach(function (type) { + Vue[type] = function ( + id, + definition + ) { + if (!definition) { + return this.options[type + 's'][id] + } else { + /* istanbul ignore if */ + { + if (type === 'component' && config.isReservedTag(id)) { + warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + id + ) + } + } + if (type === 'component' && isPlainObject(definition)) { + definition.name = definition.name || id + definition = Vue.extend(definition) + } + if (type === 'directive' && typeof definition === 'function') { + definition = { bind: definition, update: definition } + } + this.options[type + 's'][id] = definition + return definition + } + } + }) + } + + var KeepAlive = { + name: 'keep-alive', + abstract: true, + created: function created () { + this.cache = Object.create(null) + }, + render: function render () { + var vnode = getFirstComponentChild(this.$slots.default) + if (vnode && vnode.componentOptions) { + var opts = vnode.componentOptions + var key = vnode.key == null + // same constructor may get registered as different local components + // so cid alone is not enough (#3269) + ? opts.Ctor.cid + '::' + opts.tag + : vnode.key + if (this.cache[key]) { + vnode.child = this.cache[key].child + } else { + this.cache[key] = vnode + } + vnode.data.keepAlive = true + } + return vnode + }, + destroyed: function destroyed () { + var this$1 = this; + + for (var key in this.cache) { + var vnode = this$1.cache[key] + callHook(vnode.child, 'deactivated') + vnode.child.$destroy() + } + } + } + + var builtInComponents = { + KeepAlive: KeepAlive + } + + /* */ + + function initGlobalAPI (Vue) { + // config + var configDef = {} + configDef.get = function () { return config; } + { + configDef.set = function () { + warn( + 'Do not replace the Vue.config object, set individual fields instead.' + ) + } + } + Object.defineProperty(Vue, 'config', configDef) + Vue.util = util + Vue.set = set + Vue.delete = del + Vue.nextTick = nextTick + + Vue.options = Object.create(null) + config._assetTypes.forEach(function (type) { + Vue.options[type + 's'] = Object.create(null) + }) + + extend(Vue.options.components, builtInComponents) + + initUse(Vue) + initMixin$1(Vue) + initExtend(Vue) + initAssetRegisters(Vue) + } + + initGlobalAPI(Vue$3) + + Object.defineProperty(Vue$3.prototype, '$isServer', { + get: function () { return config._isServer; } + }) + + Vue$3.version = '2.0.1' + + /* */ + + // attributes that should be using props for binding + var mustUseProp = makeMap('value,selected,checked,muted') + + var isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck') + + var isBooleanAttr = makeMap( + 'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' + + 'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' + + 'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' + + 'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' + + 'required,reversed,scoped,seamless,selected,sortable,translate,' + + 'truespeed,typemustmatch,visible' + ) + + var isAttr = makeMap( + 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' + + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' + + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' + + 'form,formaction,headers,,height,hidden,high,href,hreflang,http-equiv,' + + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + + 'target,title,type,usemap,value,width,wrap' + ) + + + + var xlinkNS = 'http://www.w3.org/1999/xlink' + + var isXlink = function (name) { + return name.charAt(5) === ':' && name.slice(0, 5) === 'xlink' + } + + var getXlinkProp = function (name) { + return isXlink(name) ? name.slice(6, name.length) : '' + } + + var isFalsyAttrValue = function (val) { + return val == null || val === false + } + + /* */ + + function genClassForVnode (vnode) { + var data = vnode.data + var parentNode = vnode + var childNode = vnode + while (childNode.child) { + childNode = childNode.child._vnode + if (childNode.data) { + data = mergeClassData(childNode.data, data) + } + } + while ((parentNode = parentNode.parent)) { + if (parentNode.data) { + data = mergeClassData(data, parentNode.data) + } + } + return genClassFromData(data) + } + + function mergeClassData (child, parent) { + return { + staticClass: concat(child.staticClass, parent.staticClass), + class: child.class + ? [child.class, parent.class] + : parent.class + } + } + + function genClassFromData (data) { + var dynamicClass = data.class + var staticClass = data.staticClass + if (staticClass || dynamicClass) { + return concat(staticClass, stringifyClass(dynamicClass)) + } + /* istanbul ignore next */ + return '' + } + + function concat (a, b) { + return a ? b ? (a + ' ' + b) : a : (b || '') + } + + function stringifyClass (value) { + var res = '' + if (!value) { + return res + } + if (typeof value === 'string') { + return value + } + if (Array.isArray(value)) { + var stringified + for (var i = 0, l = value.length; i < l; i++) { + if (value[i]) { + if ((stringified = stringifyClass(value[i]))) { + res += stringified + ' ' + } + } + } + return res.slice(0, -1) + } + if (isObject(value)) { + for (var key in value) { + if (value[key]) { res += key + ' ' } + } + return res.slice(0, -1) + } + /* istanbul ignore next */ + return res + } + + /* */ + + var namespaceMap = { + svg: 'http://www.w3.org/2000/svg', + math: 'http://www.w3.org/1998/Math/MathML' + } + + var isHTMLTag = makeMap( + 'html,body,base,head,link,meta,style,title,' + + 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + + 'div,dd,dl,dt,figcaption,figure,hr,img,li,main,ol,p,pre,ul,' + + 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + + 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + + 'embed,object,param,source,canvas,script,noscript,del,ins,' + + 'caption,col,colgroup,table,thead,tbody,td,th,tr,' + + 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + + 'output,progress,select,textarea,' + + 'details,dialog,menu,menuitem,summary,' + + 'content,element,shadow,template' + ) + + var isUnaryTag = makeMap( + 'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' + + 'link,meta,param,source,track,wbr', + true + ) + + // Elements that you can, intentionally, leave open + // (and which close themselves) + var canBeLeftOpenTag = makeMap( + 'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source', + true + ) + + // HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3 + // Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content + var isNonPhrasingTag = makeMap( + 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' + + 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' + + 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' + + 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' + + 'title,tr,track', + true + ) + + // this map is intentionally selective, only covering SVG elements that may + // contain child elements. + var isSVG = makeMap( + 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font,' + + 'font-face,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' + + 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view', + true + ) + + var isPreTag = function (tag) { return tag === 'pre'; } + + var isReservedTag = function (tag) { + return isHTMLTag(tag) || isSVG(tag) + } + + function getTagNamespace (tag) { + if (isSVG(tag)) { + return 'svg' + } + // basic support for MathML + // note it doesn't support other MathML elements being component roots + if (tag === 'math') { + return 'math' + } + } + + var unknownElementCache = Object.create(null) + function isUnknownElement (tag) { + /* istanbul ignore if */ + if (!inBrowser) { + return true + } + if (isReservedTag(tag)) { + return false + } + tag = tag.toLowerCase() + /* istanbul ignore if */ + if (unknownElementCache[tag] != null) { + return unknownElementCache[tag] + } + var el = document.createElement(tag) + if (tag.indexOf('-') > -1) { + // http://stackoverflow.com/a/28210364/1070244 + return (unknownElementCache[tag] = ( + el.constructor === window.HTMLUnknownElement || + el.constructor === window.HTMLElement + )) + } else { + return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString())) + } + } + + /* */ + + /** + * Query an element selector if it's not an element already. + */ + function query (el) { + if (typeof el === 'string') { + var selector = el + el = document.querySelector(el) + if (!el) { + "development" !== 'production' && warn( + 'Cannot find element: ' + selector + ) + return document.createElement('div') + } + } + return el + } + + /* */ + + function createElement$1 (tagName) { + return document.createElement(tagName) + } + + function createElementNS (namespace, tagName) { + return document.createElementNS(namespaceMap[namespace], tagName) + } + + function createTextNode (text) { + return document.createTextNode(text) + } + + function createComment (text) { + return document.createComment(text) + } + + function insertBefore (parentNode, newNode, referenceNode) { + parentNode.insertBefore(newNode, referenceNode) + } + + function removeChild (node, child) { + node.removeChild(child) + } + + function appendChild (node, child) { + node.appendChild(child) + } + + function parentNode (node) { + return node.parentNode + } + + function nextSibling (node) { + return node.nextSibling + } + + function tagName (node) { + return node.tagName + } + + function setTextContent (node, text) { + node.textContent = text + } + + function childNodes (node) { + return node.childNodes + } + + function setAttribute (node, key, val) { + node.setAttribute(key, val) + } + + + var nodeOps = Object.freeze({ + createElement: createElement$1, + createElementNS: createElementNS, + createTextNode: createTextNode, + createComment: createComment, + insertBefore: insertBefore, + removeChild: removeChild, + appendChild: appendChild, + parentNode: parentNode, + nextSibling: nextSibling, + tagName: tagName, + setTextContent: setTextContent, + childNodes: childNodes, + setAttribute: setAttribute + }); + + /* */ + + var ref = { + create: function create (_, vnode) { + registerRef(vnode) + }, + update: function update (oldVnode, vnode) { + if (oldVnode.data.ref !== vnode.data.ref) { + registerRef(oldVnode, true) + registerRef(vnode) + } + }, + destroy: function destroy (vnode) { + registerRef(vnode, true) + } + } + + function registerRef (vnode, isRemoval) { + var key = vnode.data.ref + if (!key) { return } + + var vm = vnode.context + var ref = vnode.child || vnode.elm + var refs = vm.$refs + if (isRemoval) { + if (Array.isArray(refs[key])) { + remove$1(refs[key], ref) + } else if (refs[key] === ref) { + refs[key] = undefined + } + } else { + if (vnode.data.refInFor) { + if (Array.isArray(refs[key])) { + refs[key].push(ref) + } else { + refs[key] = [ref] + } + } else { + refs[key] = ref + } + } + } + + /** + * Virtual DOM patching algorithm based on Snabbdom by + * Simon Friis Vindum (@paldepind) + * Licensed under the MIT License + * https://github.com/paldepind/snabbdom/blob/master/LICENSE + * + * modified by Evan You (@yyx990803) + * + + /* + * Not type-checking this because this file is perf-critical and the cost + * of making flow understand it is not worth it. + */ + + var emptyData = {} + var emptyNode = new VNode('', emptyData, []) + var hooks$1 = ['create', 'update', 'postpatch', 'remove', 'destroy'] + + function isUndef (s) { + return s == null + } + + function isDef (s) { + return s != null + } + + function sameVnode (vnode1, vnode2) { + return ( + vnode1.key === vnode2.key && + vnode1.tag === vnode2.tag && + vnode1.isComment === vnode2.isComment && + !vnode1.data === !vnode2.data + ) + } + + function createKeyToOldIdx (children, beginIdx, endIdx) { + var i, key + var map = {} + for (i = beginIdx; i <= endIdx; ++i) { + key = children[i].key + if (isDef(key)) { map[key] = i } + } + return map + } + + function createPatchFunction (backend) { + var i, j + var cbs = {} + + var modules = backend.modules; + var nodeOps = backend.nodeOps; + + for (i = 0; i < hooks$1.length; ++i) { + cbs[hooks$1[i]] = [] + for (j = 0; j < modules.length; ++j) { + if (modules[j][hooks$1[i]] !== undefined) { cbs[hooks$1[i]].push(modules[j][hooks$1[i]]) } + } + } + + function emptyNodeAt (elm) { + return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm) + } + + function createRmCb (childElm, listeners) { + function remove$$1 () { + if (--remove$$1.listeners === 0) { + removeElement(childElm) + } + } + remove$$1.listeners = listeners + return remove$$1 + } + + function removeElement (el) { + var parent = nodeOps.parentNode(el) + nodeOps.removeChild(parent, el) + } + + function createElm (vnode, insertedVnodeQueue, nested) { + var i + var data = vnode.data + vnode.isRootInsert = !nested + if (isDef(data)) { + if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode) } + // after calling the init hook, if the vnode is a child component + // it should've created a child instance and mounted it. the child + // component also has set the placeholder vnode's elm. + // in that case we can just return the element and be done. + if (isDef(i = vnode.child)) { + initComponent(vnode, insertedVnodeQueue) + return vnode.elm + } + } + var children = vnode.children + var tag = vnode.tag + if (isDef(tag)) { + { + if ( + !vnode.ns && + !(config.ignoredElements && config.ignoredElements.indexOf(tag) > -1) && + config.isUnknownElement(tag) + ) { + warn( + 'Unknown custom element: <' + tag + '> - did you ' + + 'register the component correctly? For recursive components, ' + + 'make sure to provide the "name" option.', + vnode.context + ) + } + } + vnode.elm = vnode.ns + ? nodeOps.createElementNS(vnode.ns, tag) + : nodeOps.createElement(tag) + setScope(vnode) + createChildren(vnode, children, insertedVnodeQueue) + if (isDef(data)) { + invokeCreateHooks(vnode, insertedVnodeQueue) + } + } else if (vnode.isComment) { + vnode.elm = nodeOps.createComment(vnode.text) + } else { + vnode.elm = nodeOps.createTextNode(vnode.text) + } + return vnode.elm + } + + function createChildren (vnode, children, insertedVnodeQueue) { + if (Array.isArray(children)) { + for (var i = 0; i < children.length; ++i) { + nodeOps.appendChild(vnode.elm, createElm(children[i], insertedVnodeQueue, true)) + } + } else if (isPrimitive(vnode.text)) { + nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text)) + } + } + + function isPatchable (vnode) { + while (vnode.child) { + vnode = vnode.child._vnode + } + return isDef(vnode.tag) + } + + function invokeCreateHooks (vnode, insertedVnodeQueue) { + for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) { + cbs.create[i$1](emptyNode, vnode) + } + i = vnode.data.hook // Reuse variable + if (isDef(i)) { + if (i.create) { i.create(emptyNode, vnode) } + if (i.insert) { insertedVnodeQueue.push(vnode) } + } + } + + function initComponent (vnode, insertedVnodeQueue) { + if (vnode.data.pendingInsert) { + insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert) + } + vnode.elm = vnode.child.$el + if (isPatchable(vnode)) { + invokeCreateHooks(vnode, insertedVnodeQueue) + setScope(vnode) + } else { + // empty component root. + // skip all element-related modules except for ref (#3455) + registerRef(vnode) + // make sure to invoke the insert hook + insertedVnodeQueue.push(vnode) + } + } + + // set scope id attribute for scoped CSS. + // this is implemented as a special case to avoid the overhead + // of going through the normal attribute patching process. + function setScope (vnode) { + var i + if (isDef(i = vnode.context) && isDef(i = i.$options._scopeId)) { + nodeOps.setAttribute(vnode.elm, i, '') + } + if (isDef(i = activeInstance) && + i !== vnode.context && + isDef(i = i.$options._scopeId)) { + nodeOps.setAttribute(vnode.elm, i, '') + } + } + + function addVnodes (parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) { + for (; startIdx <= endIdx; ++startIdx) { + nodeOps.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before) + } + } + + function invokeDestroyHook (vnode) { + var i, j + var data = vnode.data + if (isDef(data)) { + if (isDef(i = data.hook) && isDef(i = i.destroy)) { i(vnode) } + for (i = 0; i < cbs.destroy.length; ++i) { cbs.destroy[i](vnode) } + } + if (isDef(i = vnode.child) && !data.keepAlive) { + invokeDestroyHook(i._vnode) + } + if (isDef(i = vnode.children)) { + for (j = 0; j < vnode.children.length; ++j) { + invokeDestroyHook(vnode.children[j]) + } + } + } + + function removeVnodes (parentElm, vnodes, startIdx, endIdx) { + for (; startIdx <= endIdx; ++startIdx) { + var ch = vnodes[startIdx] + if (isDef(ch)) { + if (isDef(ch.tag)) { + removeAndInvokeRemoveHook(ch) + invokeDestroyHook(ch) + } else { // Text node + nodeOps.removeChild(parentElm, ch.elm) + } + } + } + } + + function removeAndInvokeRemoveHook (vnode, rm) { + if (rm || isDef(vnode.data)) { + var listeners = cbs.remove.length + 1 + if (!rm) { + // directly removing + rm = createRmCb(vnode.elm, listeners) + } else { + // we have a recursively passed down rm callback + // increase the listeners count + rm.listeners += listeners + } + // recursively invoke hooks on child component root node + if (isDef(i = vnode.child) && isDef(i = i._vnode) && isDef(i.data)) { + removeAndInvokeRemoveHook(i, rm) + } + for (i = 0; i < cbs.remove.length; ++i) { + cbs.remove[i](vnode, rm) + } + if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) { + i(vnode, rm) + } else { + rm() + } + } else { + removeElement(vnode.elm) + } + } + + function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) { + var oldStartIdx = 0 + var newStartIdx = 0 + var oldEndIdx = oldCh.length - 1 + var oldStartVnode = oldCh[0] + var oldEndVnode = oldCh[oldEndIdx] + var newEndIdx = newCh.length - 1 + var newStartVnode = newCh[0] + var newEndVnode = newCh[newEndIdx] + var oldKeyToIdx, idxInOld, elmToMove, before + + // removeOnly is a special flag used only by + // to ensure removed elements stay in correct relative positions + // during leaving transitions + var canMove = !removeOnly + + while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { + if (isUndef(oldStartVnode)) { + oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left + } else if (isUndef(oldEndVnode)) { + oldEndVnode = oldCh[--oldEndIdx] + } else if (sameVnode(oldStartVnode, newStartVnode)) { + patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue) + oldStartVnode = oldCh[++oldStartIdx] + newStartVnode = newCh[++newStartIdx] + } else if (sameVnode(oldEndVnode, newEndVnode)) { + patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue) + oldEndVnode = oldCh[--oldEndIdx] + newEndVnode = newCh[--newEndIdx] + } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right + patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue) + canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm)) + oldStartVnode = oldCh[++oldStartIdx] + newEndVnode = newCh[--newEndIdx] + } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left + patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue) + canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm) + oldEndVnode = oldCh[--oldEndIdx] + newStartVnode = newCh[++newStartIdx] + } else { + if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx) } + idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null + if (isUndef(idxInOld)) { // New element + nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm) + newStartVnode = newCh[++newStartIdx] + } else { + elmToMove = oldCh[idxInOld] + /* istanbul ignore if */ + if ("development" !== 'production' && !elmToMove) { + warn( + 'It seems there are duplicate keys that is causing an update error. ' + + 'Make sure each v-for item has a unique key.' + ) + } + if (elmToMove.tag !== newStartVnode.tag) { + // same key but different element. treat as new element + nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm) + newStartVnode = newCh[++newStartIdx] + } else { + patchVnode(elmToMove, newStartVnode, insertedVnodeQueue) + oldCh[idxInOld] = undefined + canMove && nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm) + newStartVnode = newCh[++newStartIdx] + } + } + } + } + if (oldStartIdx > oldEndIdx) { + before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm + addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue) + } else if (newStartIdx > newEndIdx) { + removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx) + } + } + + function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) { + if (oldVnode === vnode) { + return + } + // reuse element for static trees. + // note we only do this if the vnode is cloned - + // if the new node is not cloned it means the render functions have been + // reset by the hot-reload-api and we need to do a proper re-render. + if (vnode.isStatic && + oldVnode.isStatic && + vnode.key === oldVnode.key && + vnode.isCloned) { + vnode.elm = oldVnode.elm + return + } + var i, hook + var hasData = isDef(i = vnode.data) + if (hasData && isDef(hook = i.hook) && isDef(i = hook.prepatch)) { + i(oldVnode, vnode) + } + var elm = vnode.elm = oldVnode.elm + var oldCh = oldVnode.children + var ch = vnode.children + if (hasData && isPatchable(vnode)) { + for (i = 0; i < cbs.update.length; ++i) { cbs.update[i](oldVnode, vnode) } + if (isDef(hook) && isDef(i = hook.update)) { i(oldVnode, vnode) } + } + if (isUndef(vnode.text)) { + if (isDef(oldCh) && isDef(ch)) { + if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly) } + } else if (isDef(ch)) { + if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, '') } + addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue) + } else if (isDef(oldCh)) { + removeVnodes(elm, oldCh, 0, oldCh.length - 1) + } else if (isDef(oldVnode.text)) { + nodeOps.setTextContent(elm, '') + } + } else if (oldVnode.text !== vnode.text) { + nodeOps.setTextContent(elm, vnode.text) + } + if (hasData) { + for (i = 0; i < cbs.postpatch.length; ++i) { cbs.postpatch[i](oldVnode, vnode) } + if (isDef(hook) && isDef(i = hook.postpatch)) { i(oldVnode, vnode) } + } + } + + function invokeInsertHook (vnode, queue, initial) { + // delay insert hooks for component root nodes, invoke them after the + // element is really inserted + if (initial && vnode.parent) { + vnode.parent.data.pendingInsert = queue + } else { + for (var i = 0; i < queue.length; ++i) { + queue[i].data.hook.insert(queue[i]) + } + } + } + + var bailed = false + function hydrate (elm, vnode, insertedVnodeQueue) { + { + if (!assertNodeMatch(elm, vnode)) { + return false + } + } + vnode.elm = elm + var tag = vnode.tag; + var data = vnode.data; + var children = vnode.children; + if (isDef(data)) { + if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */) } + if (isDef(i = vnode.child)) { + // child component. it should have hydrated its own tree. + initComponent(vnode, insertedVnodeQueue) + return true + } + } + if (isDef(tag)) { + if (isDef(children)) { + var childNodes = nodeOps.childNodes(elm) + // empty element, allow client to pick up and populate children + if (!childNodes.length) { + createChildren(vnode, children, insertedVnodeQueue) + } else { + var childrenMatch = true + if (childNodes.length !== children.length) { + childrenMatch = false + } else { + for (var i$1 = 0; i$1 < children.length; i$1++) { + if (!hydrate(childNodes[i$1], children[i$1], insertedVnodeQueue)) { + childrenMatch = false + break + } + } + } + if (!childrenMatch) { + if ("development" !== 'production' && + typeof console !== 'undefined' && + !bailed) { + bailed = true + console.warn('Parent: ', elm) + console.warn('Mismatching childNodes vs. VNodes: ', childNodes, children) + } + return false + } + } + } + if (isDef(data)) { + invokeCreateHooks(vnode, insertedVnodeQueue) + } + } + return true + } + + function assertNodeMatch (node, vnode) { + if (vnode.tag) { + return ( + vnode.tag.indexOf('vue-component') === 0 || + vnode.tag === nodeOps.tagName(node).toLowerCase() + ) + } else { + return _toString(vnode.text) === node.data + } + } + + return function patch (oldVnode, vnode, hydrating, removeOnly) { + var elm, parent + var isInitialPatch = false + var insertedVnodeQueue = [] + + if (!oldVnode) { + // empty mount, create new root element + isInitialPatch = true + createElm(vnode, insertedVnodeQueue) + } else { + var isRealElement = isDef(oldVnode.nodeType) + if (!isRealElement && sameVnode(oldVnode, vnode)) { + patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) + } else { + if (isRealElement) { + // mounting to a real element + // check if this is server-rendered content and if we can perform + // a successful hydration. + if (oldVnode.nodeType === 1 && oldVnode.hasAttribute('server-rendered')) { + oldVnode.removeAttribute('server-rendered') + hydrating = true + } + if (hydrating) { + if (hydrate(oldVnode, vnode, insertedVnodeQueue)) { + invokeInsertHook(vnode, insertedVnodeQueue, true) + return oldVnode + } else { + warn( + 'The client-side rendered virtual DOM tree is not matching ' + + 'server-rendered content. This is likely caused by incorrect ' + + 'HTML markup, for example nesting block-level elements inside ' + + '

, or missing . Bailing hydration and performing ' + + 'full client-side render.' + ) + } + } + // either not server-rendered, or hydration failed. + // create an empty node and replace it + oldVnode = emptyNodeAt(oldVnode) + } + elm = oldVnode.elm + parent = nodeOps.parentNode(elm) + + createElm(vnode, insertedVnodeQueue) + + // component root element replaced. + // update parent placeholder node element. + if (vnode.parent) { + vnode.parent.elm = vnode.elm + if (isPatchable(vnode)) { + for (var i = 0; i < cbs.create.length; ++i) { + cbs.create[i](emptyNode, vnode.parent) + } + } + } + + if (parent !== null) { + nodeOps.insertBefore(parent, vnode.elm, nodeOps.nextSibling(elm)) + removeVnodes(parent, [oldVnode], 0, 0) + } else if (isDef(oldVnode.tag)) { + invokeDestroyHook(oldVnode) + } + } + } + + invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch) + return vnode.elm + } + } + + /* */ + + var directives = { + create: function bindDirectives (oldVnode, vnode) { + var hasInsert = false + forEachDirective(oldVnode, vnode, function (def, dir) { + callHook$1(def, dir, 'bind', vnode, oldVnode) + if (def.inserted) { + hasInsert = true + } + }) + if (hasInsert) { + mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', function () { + applyDirectives(oldVnode, vnode, 'inserted') + }) + } + }, + update: function updateDirectives (oldVnode, vnode) { + applyDirectives(oldVnode, vnode, 'update') + // if old vnode has directives but new vnode doesn't + // we need to teardown the directives on the old one. + if (oldVnode.data.directives && !vnode.data.directives) { + applyDirectives(oldVnode, oldVnode, 'unbind') + } + }, + postpatch: function postupdateDirectives (oldVnode, vnode) { + applyDirectives(oldVnode, vnode, 'componentUpdated') + }, + destroy: function unbindDirectives (vnode) { + applyDirectives(vnode, vnode, 'unbind') + } + } + + var emptyModifiers = Object.create(null) + + function forEachDirective ( + oldVnode, + vnode, + fn + ) { + var dirs = vnode.data.directives + if (dirs) { + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i] + var def = resolveAsset(vnode.context.$options, 'directives', dir.name, true) + if (def) { + var oldDirs = oldVnode && oldVnode.data.directives + if (oldDirs) { + dir.oldValue = oldDirs[i].value + } + if (!dir.modifiers) { + dir.modifiers = emptyModifiers + } + fn(def, dir) + } + } + } + } + + function applyDirectives ( + oldVnode, + vnode, + hook + ) { + forEachDirective(oldVnode, vnode, function (def, dir) { + callHook$1(def, dir, hook, vnode, oldVnode) + }) + } + + function callHook$1 (def, dir, hook, vnode, oldVnode) { + var fn = def && def[hook] + if (fn) { + fn(vnode.elm, dir, vnode, oldVnode) + } + } + + var baseModules = [ + ref, + directives + ] + + /* */ + + function updateAttrs (oldVnode, vnode) { + if (!oldVnode.data.attrs && !vnode.data.attrs) { + return + } + var key, cur, old + var elm = vnode.elm + var oldAttrs = oldVnode.data.attrs || {} + var attrs = vnode.data.attrs || {} + // clone observed objects, as the user probably wants to mutate it + if (attrs.__ob__) { + attrs = vnode.data.attrs = extend({}, attrs) + } + + for (key in attrs) { + cur = attrs[key] + old = oldAttrs[key] + if (old !== cur) { + setAttr(elm, key, cur) + } + } + for (key in oldAttrs) { + if (attrs[key] == null) { + if (isXlink(key)) { + elm.removeAttributeNS(xlinkNS, getXlinkProp(key)) + } else if (!isEnumeratedAttr(key)) { + elm.removeAttribute(key) + } + } + } + } + + function setAttr (el, key, value) { + if (isBooleanAttr(key)) { + // set attribute for blank value + // e.g. + if (isFalsyAttrValue(value)) { + el.removeAttribute(key) + } else { + el.setAttribute(key, key) + } + } else if (isEnumeratedAttr(key)) { + el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true') + } else if (isXlink(key)) { + if (isFalsyAttrValue(value)) { + el.removeAttributeNS(xlinkNS, getXlinkProp(key)) + } else { + el.setAttributeNS(xlinkNS, key, value) + } + } else { + if (isFalsyAttrValue(value)) { + el.removeAttribute(key) + } else { + el.setAttribute(key, value) + } + } + } + + var attrs = { + create: updateAttrs, + update: updateAttrs + } + + /* */ + + function updateClass (oldVnode, vnode) { + var el = vnode.elm + var data = vnode.data + var oldData = oldVnode.data + if (!data.staticClass && !data.class && + (!oldData || (!oldData.staticClass && !oldData.class))) { + return + } + + var cls = genClassForVnode(vnode) + + // handle transition classes + var transitionClass = el._transitionClasses + if (transitionClass) { + cls = concat(cls, stringifyClass(transitionClass)) + } + + // set the class + if (cls !== el._prevClass) { + el.setAttribute('class', cls) + el._prevClass = cls + } + } + + var klass = { + create: updateClass, + update: updateClass + } + + // skip type checking this file because we need to attach private properties + // to elements + + function updateDOMListeners (oldVnode, vnode) { + if (!oldVnode.data.on && !vnode.data.on) { + return + } + var on = vnode.data.on || {} + var oldOn = oldVnode.data.on || {} + var add = vnode.elm._v_add || (vnode.elm._v_add = function (event, handler, capture) { + vnode.elm.addEventListener(event, handler, capture) + }) + var remove = vnode.elm._v_remove || (vnode.elm._v_remove = function (event, handler) { + vnode.elm.removeEventListener(event, handler) + }) + updateListeners(on, oldOn, add, remove) + } + + var events = { + create: updateDOMListeners, + update: updateDOMListeners + } + + /* */ + + function updateDOMProps (oldVnode, vnode) { + if (!oldVnode.data.domProps && !vnode.data.domProps) { + return + } + var key, cur + var elm = vnode.elm + var oldProps = oldVnode.data.domProps || {} + var props = vnode.data.domProps || {} + // clone observed objects, as the user probably wants to mutate it + if (props.__ob__) { + props = vnode.data.domProps = extend({}, props) + } + + for (key in oldProps) { + if (props[key] == null) { + elm[key] = undefined + } + } + for (key in props) { + // ignore children if the node has textContent or innerHTML, + // as these will throw away existing DOM nodes and cause removal errors + // on subsequent patches (#3360) + if ((key === 'textContent' || key === 'innerHTML') && vnode.children) { + vnode.children.length = 0 + } + cur = props[key] + if (key === 'value') { + // store value as _value as well since + // non-string values will be stringified + elm._value = cur + // avoid resetting cursor position when value is the same + var strCur = cur == null ? '' : String(cur) + if (elm.value !== strCur) { + elm.value = strCur + } + } else { + elm[key] = cur + } + } + } + + var domProps = { + create: updateDOMProps, + update: updateDOMProps + } + + /* */ + + var prefixes = ['Webkit', 'Moz', 'ms'] + + var testEl + var normalize = cached(function (prop) { + testEl = testEl || document.createElement('div') + prop = camelize(prop) + if (prop !== 'filter' && (prop in testEl.style)) { + return prop + } + var upper = prop.charAt(0).toUpperCase() + prop.slice(1) + for (var i = 0; i < prefixes.length; i++) { + var prefixed = prefixes[i] + upper + if (prefixed in testEl.style) { + return prefixed + } + } + }) + + function updateStyle (oldVnode, vnode) { + if ((!oldVnode.data || !oldVnode.data.style) && !vnode.data.style) { + return + } + var cur, name + var el = vnode.elm + var oldStyle = oldVnode.data.style || {} + var style = vnode.data.style || {} + + // handle string + if (typeof style === 'string') { + el.style.cssText = style + return + } + + var needClone = style.__ob__ + + // handle array syntax + if (Array.isArray(style)) { + style = vnode.data.style = toObject(style) + } + + // clone the style for future updates, + // in case the user mutates the style object in-place. + if (needClone) { + style = vnode.data.style = extend({}, style) + } + + for (name in oldStyle) { + if (!style[name]) { + el.style[normalize(name)] = '' + } + } + for (name in style) { + cur = style[name] + if (cur !== oldStyle[name]) { + // ie9 setting to null has no effect, must use empty string + el.style[normalize(name)] = cur == null ? '' : cur + } + } + } + + var style = { + create: updateStyle, + update: updateStyle + } + + /* */ + + /** + * Add class with compatibility for SVG since classList is not supported on + * SVG elements in IE + */ + function addClass (el, cls) { + /* istanbul ignore else */ + if (el.classList) { + if (cls.indexOf(' ') > -1) { + cls.split(/\s+/).forEach(function (c) { return el.classList.add(c); }) + } else { + el.classList.add(cls) + } + } else { + var cur = ' ' + el.getAttribute('class') + ' ' + if (cur.indexOf(' ' + cls + ' ') < 0) { + el.setAttribute('class', (cur + cls).trim()) + } + } + } + + /** + * Remove class with compatibility for SVG since classList is not supported on + * SVG elements in IE + */ + function removeClass (el, cls) { + /* istanbul ignore else */ + if (el.classList) { + if (cls.indexOf(' ') > -1) { + cls.split(/\s+/).forEach(function (c) { return el.classList.remove(c); }) + } else { + el.classList.remove(cls) + } + } else { + var cur = ' ' + el.getAttribute('class') + ' ' + var tar = ' ' + cls + ' ' + while (cur.indexOf(tar) >= 0) { + cur = cur.replace(tar, ' ') + } + el.setAttribute('class', cur.trim()) + } + } + + /* */ + + var hasTransition = inBrowser && !isIE9 + var TRANSITION = 'transition' + var ANIMATION = 'animation' + + // Transition property/event sniffing + var transitionProp = 'transition' + var transitionEndEvent = 'transitionend' + var animationProp = 'animation' + var animationEndEvent = 'animationend' + if (hasTransition) { + /* istanbul ignore if */ + if (window.ontransitionend === undefined && + window.onwebkittransitionend !== undefined) { + transitionProp = 'WebkitTransition' + transitionEndEvent = 'webkitTransitionEnd' + } + if (window.onanimationend === undefined && + window.onwebkitanimationend !== undefined) { + animationProp = 'WebkitAnimation' + animationEndEvent = 'webkitAnimationEnd' + } + } + + var raf = (inBrowser && window.requestAnimationFrame) || setTimeout + function nextFrame (fn) { + raf(function () { + raf(fn) + }) + } + + function addTransitionClass (el, cls) { + (el._transitionClasses || (el._transitionClasses = [])).push(cls) + addClass(el, cls) + } + + function removeTransitionClass (el, cls) { + if (el._transitionClasses) { + remove$1(el._transitionClasses, cls) + } + removeClass(el, cls) + } + + function whenTransitionEnds ( + el, + expectedType, + cb + ) { + var ref = getTransitionInfo(el, expectedType); + var type = ref.type; + var timeout = ref.timeout; + var propCount = ref.propCount; + if (!type) { return cb() } + var event = type === TRANSITION ? transitionEndEvent : animationEndEvent + var ended = 0 + var end = function () { + el.removeEventListener(event, onEnd) + cb() + } + var onEnd = function (e) { + if (e.target === el) { + if (++ended >= propCount) { + end() + } + } + } + setTimeout(function () { + if (ended < propCount) { + end() + } + }, timeout + 1) + el.addEventListener(event, onEnd) + } + + var transformRE = /\b(transform|all)(,|$)/ + + function getTransitionInfo (el, expectedType) { + var styles = window.getComputedStyle(el) + var transitioneDelays = styles[transitionProp + 'Delay'].split(', ') + var transitionDurations = styles[transitionProp + 'Duration'].split(', ') + var transitionTimeout = getTimeout(transitioneDelays, transitionDurations) + var animationDelays = styles[animationProp + 'Delay'].split(', ') + var animationDurations = styles[animationProp + 'Duration'].split(', ') + var animationTimeout = getTimeout(animationDelays, animationDurations) + + var type + var timeout = 0 + var propCount = 0 + /* istanbul ignore if */ + if (expectedType === TRANSITION) { + if (transitionTimeout > 0) { + type = TRANSITION + timeout = transitionTimeout + propCount = transitionDurations.length + } + } else if (expectedType === ANIMATION) { + if (animationTimeout > 0) { + type = ANIMATION + timeout = animationTimeout + propCount = animationDurations.length + } + } else { + timeout = Math.max(transitionTimeout, animationTimeout) + type = timeout > 0 + ? transitionTimeout > animationTimeout + ? TRANSITION + : ANIMATION + : null + propCount = type + ? type === TRANSITION + ? transitionDurations.length + : animationDurations.length + : 0 + } + var hasTransform = + type === TRANSITION && + transformRE.test(styles[transitionProp + 'Property']) + return { + type: type, + timeout: timeout, + propCount: propCount, + hasTransform: hasTransform + } + } + + function getTimeout (delays, durations) { + return Math.max.apply(null, durations.map(function (d, i) { + return toMs(d) + toMs(delays[i]) + })) + } + + function toMs (s) { + return Number(s.slice(0, -1)) * 1000 + } + + /* */ + + function enter (vnode) { + var el = vnode.elm + + // call leave callback now + if (el._leaveCb) { + el._leaveCb.cancelled = true + el._leaveCb() + } + + var data = resolveTransition(vnode.data.transition) + if (!data) { + return + } + + /* istanbul ignore if */ + if (el._enterCb || el.nodeType !== 1) { + return + } + + var css = data.css; + var type = data.type; + var enterClass = data.enterClass; + var enterActiveClass = data.enterActiveClass; + var appearClass = data.appearClass; + var appearActiveClass = data.appearActiveClass; + var beforeEnter = data.beforeEnter; + var enter = data.enter; + var afterEnter = data.afterEnter; + var enterCancelled = data.enterCancelled; + var beforeAppear = data.beforeAppear; + var appear = data.appear; + var afterAppear = data.afterAppear; + var appearCancelled = data.appearCancelled; + + // activeInstance will always be the component managing this + // transition. One edge case to check is when the is placed + // as the root node of a child component. In that case we need to check + // 's parent for appear check. + var transitionNode = activeInstance.$vnode + var context = transitionNode && transitionNode.parent + ? transitionNode.parent.context + : activeInstance + + var isAppear = !context._isMounted || !vnode.isRootInsert + + if (isAppear && !appear && appear !== '') { + return + } + + var startClass = isAppear ? appearClass : enterClass + var activeClass = isAppear ? appearActiveClass : enterActiveClass + var beforeEnterHook = isAppear ? (beforeAppear || beforeEnter) : beforeEnter + var enterHook = isAppear ? (typeof appear === 'function' ? appear : enter) : enter + var afterEnterHook = isAppear ? (afterAppear || afterEnter) : afterEnter + var enterCancelledHook = isAppear ? (appearCancelled || enterCancelled) : enterCancelled + + var expectsCSS = css !== false && !isIE9 + var userWantsControl = + enterHook && + // enterHook may be a bound method which exposes + // the length of original fn as _length + (enterHook._length || enterHook.length) > 1 + + var cb = el._enterCb = once(function () { + if (expectsCSS) { + removeTransitionClass(el, activeClass) + } + if (cb.cancelled) { + if (expectsCSS) { + removeTransitionClass(el, startClass) + } + enterCancelledHook && enterCancelledHook(el) + } else { + afterEnterHook && afterEnterHook(el) + } + el._enterCb = null + }) + + if (!vnode.data.show) { + // remove pending leave element on enter by injecting an insert hook + mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', function () { + var parent = el.parentNode + var pendingNode = parent && parent._pending && parent._pending[vnode.key] + if (pendingNode && pendingNode.tag === vnode.tag && pendingNode.elm._leaveCb) { + pendingNode.elm._leaveCb() + } + enterHook && enterHook(el, cb) + }) + } + + // start enter transition + beforeEnterHook && beforeEnterHook(el) + if (expectsCSS) { + addTransitionClass(el, startClass) + addTransitionClass(el, activeClass) + nextFrame(function () { + removeTransitionClass(el, startClass) + if (!cb.cancelled && !userWantsControl) { + whenTransitionEnds(el, type, cb) + } + }) + } + + if (vnode.data.show) { + enterHook && enterHook(el, cb) + } + + if (!expectsCSS && !userWantsControl) { + cb() + } + } + + function leave (vnode, rm) { + var el = vnode.elm + + // call enter callback now + if (el._enterCb) { + el._enterCb.cancelled = true + el._enterCb() + } + + var data = resolveTransition(vnode.data.transition) + if (!data) { + return rm() + } + + /* istanbul ignore if */ + if (el._leaveCb || el.nodeType !== 1) { + return + } + + var css = data.css; + var type = data.type; + var leaveClass = data.leaveClass; + var leaveActiveClass = data.leaveActiveClass; + var beforeLeave = data.beforeLeave; + var leave = data.leave; + var afterLeave = data.afterLeave; + var leaveCancelled = data.leaveCancelled; + var delayLeave = data.delayLeave; + + var expectsCSS = css !== false && !isIE9 + var userWantsControl = + leave && + // leave hook may be a bound method which exposes + // the length of original fn as _length + (leave._length || leave.length) > 1 + + var cb = el._leaveCb = once(function () { + if (el.parentNode && el.parentNode._pending) { + el.parentNode._pending[vnode.key] = null + } + if (expectsCSS) { + removeTransitionClass(el, leaveActiveClass) + } + if (cb.cancelled) { + if (expectsCSS) { + removeTransitionClass(el, leaveClass) + } + leaveCancelled && leaveCancelled(el) + } else { + rm() + afterLeave && afterLeave(el) + } + el._leaveCb = null + }) + + if (delayLeave) { + delayLeave(performLeave) + } else { + performLeave() + } + + function performLeave () { + // the delayed leave may have already been cancelled + if (cb.cancelled) { + return + } + // record leaving element + if (!vnode.data.show) { + (el.parentNode._pending || (el.parentNode._pending = {}))[vnode.key] = vnode + } + beforeLeave && beforeLeave(el) + if (expectsCSS) { + addTransitionClass(el, leaveClass) + addTransitionClass(el, leaveActiveClass) + nextFrame(function () { + removeTransitionClass(el, leaveClass) + if (!cb.cancelled && !userWantsControl) { + whenTransitionEnds(el, type, cb) + } + }) + } + leave && leave(el, cb) + if (!expectsCSS && !userWantsControl) { + cb() + } + } + } + + function resolveTransition (def$$1) { + if (!def$$1) { + return + } + /* istanbul ignore else */ + if (typeof def$$1 === 'object') { + var res = {} + if (def$$1.css !== false) { + extend(res, autoCssTransition(def$$1.name || 'v')) + } + extend(res, def$$1) + return res + } else if (typeof def$$1 === 'string') { + return autoCssTransition(def$$1) + } + } + + var autoCssTransition = cached(function (name) { + return { + enterClass: (name + "-enter"), + leaveClass: (name + "-leave"), + appearClass: (name + "-enter"), + enterActiveClass: (name + "-enter-active"), + leaveActiveClass: (name + "-leave-active"), + appearActiveClass: (name + "-enter-active") + } + }) + + function once (fn) { + var called = false + return function () { + if (!called) { + called = true + fn() + } + } + } + + var transition = inBrowser ? { + create: function create (_, vnode) { + if (!vnode.data.show) { + enter(vnode) + } + }, + remove: function remove (vnode, rm) { + /* istanbul ignore else */ + if (!vnode.data.show) { + leave(vnode, rm) + } else { + rm() + } + } + } : {} + + var platformModules = [ + attrs, + klass, + events, + domProps, + style, + transition + ] + + /* */ + + // the directive module should be applied last, after all + // built-in modules have been applied. + var modules = platformModules.concat(baseModules) + + var patch$1 = createPatchFunction({ nodeOps: nodeOps, modules: modules }) + + /** + * Not type checking this file because flow doesn't like attaching + * properties to Elements. + */ + + var modelableTagRE = /^input|select|textarea|vue-component-[0-9]+(-[0-9a-zA-Z_\-]*)?$/ + + /* istanbul ignore if */ + if (isIE9) { + // http://www.matts411.com/post/internet-explorer-9-oninput/ + document.addEventListener('selectionchange', function () { + var el = document.activeElement + if (el && el.vmodel) { + trigger(el, 'input') + } + }) + } + + var model = { + bind: function bind (el, binding, vnode) { + { + if (!modelableTagRE.test(vnode.tag)) { + warn( + "v-model is not supported on element type: <" + (vnode.tag) + ">. " + + 'If you are working with contenteditable, it\'s recommended to ' + + 'wrap a library dedicated for that purpose inside a custom component.', + vnode.context + ) + } + } + if (vnode.tag === 'select') { + setSelected(el, binding, vnode.context) + /* istanbul ignore if */ + if (isIE || isEdge) { + var cb = function () { + setSelected(el, binding, vnode.context) + } + nextTick(cb) + setTimeout(cb, 0) + } + } else if (vnode.tag === 'textarea' || el.type === 'text') { + if (!isAndroid) { + el.addEventListener('compositionstart', onCompositionStart) + el.addEventListener('compositionend', onCompositionEnd) + } + /* istanbul ignore if */ + if (isIE9) { + el.vmodel = true + } + } + }, + componentUpdated: function componentUpdated (el, binding, vnode) { + if (vnode.tag === 'select') { + setSelected(el, binding, vnode.context) + // in case the options rendered by v-for have changed, + // it's possible that the value is out-of-sync with the rendered options. + // detect such cases and filter out values that no longer has a matchig + // option in the DOM. + var needReset = el.multiple + ? binding.value.some(function (v) { return hasNoMatchingOption(v, el.options); }) + : hasNoMatchingOption(binding.value, el.options) + if (needReset) { + trigger(el, 'change') + } + } + } + } + + function setSelected (el, binding, vm) { + var value = binding.value + var isMultiple = el.multiple + if (isMultiple && !Array.isArray(value)) { + "development" !== 'production' && warn( + "