diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index 37cd0a6a4ca..11f8b87328c 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -103,7 +103,7 @@ public function latest($count = 20, $page = 0) * @param int $page * @return array */ - public function entityActivity($entity, $count = 20, $page = 0) + public function entityActivity($entity, $count = 20, $page = 1) { if ($entity->isA('book')) { $query = $this->activity->where('book_id', '=', $entity->id); @@ -114,7 +114,7 @@ public function entityActivity($entity, $count = 20, $page = 0) $activity = $this->permissionService ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type') - ->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * $page)->take($count)->get(); + ->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * ($page - 1))->take($count)->get(); return $this->filterSimilar($activity); } diff --git a/app/Actions/ViewService.php b/app/Actions/ViewService.php index d5f8002fc04..532f31c423c 100644 --- a/app/Actions/ViewService.php +++ b/app/Actions/ViewService.php @@ -2,21 +2,26 @@ use BookStack\Auth\Permissions\PermissionService; use BookStack\Entities\Entity; +use BookStack\Entities\EntityProvider; +use Illuminate\Support\Collection; class ViewService { protected $view; protected $permissionService; + protected $entityProvider; /** * ViewService constructor. * @param \BookStack\Actions\View $view * @param \BookStack\Auth\Permissions\PermissionService $permissionService + * @param EntityProvider $entityProvider */ - public function __construct(View $view, PermissionService $permissionService) + public function __construct(View $view, PermissionService $permissionService, EntityProvider $entityProvider) { $this->view = $view; $this->permissionService = $permissionService; + $this->entityProvider = $entityProvider; } /** @@ -50,23 +55,21 @@ public function add(Entity $entity) * Get the entities with the most views. * @param int $count * @param int $page - * @param Entity|false|array $filterModel + * @param string|array $filterModels * @param string $action - used for permission checking - * @return + * @return Collection */ - public function getPopular($count = 10, $page = 0, $filterModel = false, $action = 'view') + public function getPopular(int $count = 10, int $page = 0, $filterModels = null, string $action = 'view') { - // TODO - Standardise input filter $skipCount = $count * $page; - $query = $this->permissionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action) + $query = $this->permissionService + ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action) ->select('*', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count')) ->groupBy('viewable_id', 'viewable_type') ->orderBy('view_count', 'desc'); - if ($filterModel && is_array($filterModel)) { - $query->whereIn('viewable_type', $filterModel); - } else if ($filterModel) { - $query->where('viewable_type', '=', $filterModel->getMorphClass()); + if ($filterModels) { + $query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels)); } return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable'); diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 8fc70e916db..1e1ee394691 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -704,7 +704,7 @@ public function enforceEntityRestrictions($entityType, $query, $action = 'view') * @param string $entityIdColumn * @param string $entityTypeColumn * @param string $action - * @return mixed + * @return QueryBuilder */ public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn, $action = 'view') { diff --git a/app/Auth/Role.php b/app/Auth/Role.php index c8bb47e4582..917d8aa2619 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -1,6 +1,7 @@ belongsToMany(User::class); + return $this->belongsToMany(User::class)->orderBy('name', 'asc'); } /** @@ -30,7 +31,7 @@ public function jointPermissions() */ public function permissions() { - return $this->belongsToMany(Permissions\RolePermission::class, 'permission_role', 'role_id', 'permission_id'); + return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id'); } /** @@ -51,18 +52,18 @@ public function hasPermission($permissionName) /** * Add a permission to this role. - * @param \BookStack\Auth\Permissions\RolePermission $permission + * @param RolePermission $permission */ - public function attachPermission(Permissions\RolePermission $permission) + public function attachPermission(RolePermission $permission) { $this->permissions()->attach($permission->id); } /** * Detach a single permission from this role. - * @param \BookStack\Auth\Permissions\RolePermission $permission + * @param RolePermission $permission */ - public function detachPermission(Permissions\RolePermission $permission) + public function detachPermission(RolePermission $permission) { $this->permissions()->detach($permission->id); } diff --git a/app/Auth/UserRepo.php b/app/Auth/UserRepo.php index 31b91108d2b..1a73d0072fb 100644 --- a/app/Auth/UserRepo.php +++ b/app/Auth/UserRepo.php @@ -6,6 +6,7 @@ use BookStack\Exceptions\UserUpdateException; use BookStack\Uploads\Image; use Exception; +use Illuminate\Database\Eloquent\Builder; use Images; class UserRepo @@ -48,7 +49,7 @@ public function getById($id) /** * Get all the users with their permissions. - * @return \Illuminate\Database\Eloquent\Builder|static + * @return Builder|static */ public function getAllUsers() { @@ -59,7 +60,7 @@ public function getAllUsers() * Get all the users with their permissions in a paginated format. * @param int $count * @param $sortData - * @return \Illuminate\Database\Eloquent\Builder|static + * @return Builder|static */ public function getAllUsersPaginatedAndSorted($count, $sortData) { @@ -223,16 +224,15 @@ public function getActivity(User $user, $count = 20, $page = 0) */ public function getRecentlyCreated(User $user, $count = 20) { + $createdByUserQuery = function(Builder $query) use ($user) { + $query->where('created_by', '=', $user->id); + }; + return [ - 'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }), - 'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }), - 'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }) + 'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, $createdByUserQuery), + 'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, $createdByUserQuery), + 'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, $createdByUserQuery), + 'shelves' => $this->entityRepo->getRecentlyCreated('bookshelf', $count, 0, $createdByUserQuery) ]; } @@ -247,6 +247,7 @@ public function getAssetCounts(User $user) 'pages' => $this->entityRepo->getUserTotalCreated('page', $user), 'chapters' => $this->entityRepo->getUserTotalCreated('chapter', $user), 'books' => $this->entityRepo->getUserTotalCreated('book', $user), + 'shelves' => $this->entityRepo->getUserTotalCreated('bookshelf', $user), ]; } @@ -256,7 +257,7 @@ public function getAssetCounts(User $user) */ public function getAllRoles() { - return $this->role->all(); + return $this->role->newQuery()->orderBy('name', 'asc')->get(); } /** diff --git a/app/Entities/Book.php b/app/Entities/Book.php index 5ab5142c9f0..77cacf632e0 100644 --- a/app/Entities/Book.php +++ b/app/Entities/Book.php @@ -38,7 +38,7 @@ public function getUrl($path = false) */ public function getBookCover($width = 440, $height = 250) { - $default = baseUrl('/book_default_cover.png'); + $default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; if (!$this->image_id) { return $default; } @@ -69,6 +69,15 @@ public function pages() return $this->hasMany(Page::class); } + /** + * Get the direct child pages of this book. + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function directPages() + { + return $this->pages()->where('chapter_id', '=', '0'); + } + /** * Get all chapters within this book. * @return \Illuminate\Database\Eloquent\Relations\HasMany @@ -92,7 +101,7 @@ public function shelves() * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { $description = $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; diff --git a/app/Entities/Bookshelf.php b/app/Entities/Bookshelf.php index c37e36b59f8..08ce8d8cba0 100644 --- a/app/Entities/Bookshelf.php +++ b/app/Entities/Bookshelf.php @@ -50,7 +50,8 @@ public function getUrl($path = false) */ public function getBookCover($width = 440, $height = 250) { - $default = baseUrl('/book_default_cover.png'); + // TODO - Make generic, focused on books right now, Perhaps set-up a better image + $default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; if (!$this->image_id) { return $default; } @@ -64,7 +65,7 @@ public function getBookCover($width = 440, $height = 250) } /** - * Get the cover image of the book + * Get the cover image of the shelf * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function cover() @@ -77,7 +78,7 @@ public function cover() * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { $description = $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; @@ -91,4 +92,14 @@ public function entityRawQuery() { return "'BookStack\\\\BookShelf' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text,'' as html, '0' as book_id, '0' as priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at"; } + + /** + * Check if this shelf contains the given book. + * @param Book $book + * @return bool + */ + public function contains(Book $book) + { + return $this->books()->where('id', '=', $book->id)->count() > 0; + } } diff --git a/app/Entities/BreadcrumbsViewComposer.php b/app/Entities/BreadcrumbsViewComposer.php new file mode 100644 index 00000000000..7745d9aee54 --- /dev/null +++ b/app/Entities/BreadcrumbsViewComposer.php @@ -0,0 +1,34 @@ +entityContextManager = $entityContextManager; + } + + /** + * Modify data when the view is composed. + * @param View $view + */ + public function compose(View $view) + { + $crumbs = $view->getData()['crumbs']; + if (array_first($crumbs) instanceof Book) { + $shelf = $this->entityContextManager->getContextualShelfForBook(array_first($crumbs)); + if ($shelf) { + array_unshift($crumbs, $shelf); + $view->with('crumbs', $crumbs); + } + } + } +} \ No newline at end of file diff --git a/app/Entities/Chapter.php b/app/Entities/Chapter.php index 079105ba92a..bdacb7c9d83 100644 --- a/app/Entities/Chapter.php +++ b/app/Entities/Chapter.php @@ -53,9 +53,9 @@ public function getUrl($path = false) * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { - $description = $this->description; + $description = $this->text ?? $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; } @@ -67,4 +67,13 @@ public function entityRawQuery() { return "'BookStack\\\\Chapter' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text, '' as html, book_id, priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at"; } + + /** + * Check if this chapter has any child pages. + * @return bool + */ + public function hasChildren() + { + return count($this->pages) > 0; + } } diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index 21d172e708a..482d217662a 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -102,6 +102,11 @@ public function views() return $this->morphMany(View::class, 'viewable'); } + public function viewCountQuery() + { + return $this->views()->selectRaw('viewable_id, sum(views) as view_count')->groupBy('viewable_id'); + } + /** * Get the Tag models that have been user assigned to this entity. * @return \Illuminate\Database\Eloquent\Relations\MorphMany @@ -218,6 +223,20 @@ public function getText() return $this->{$this->textField}; } + /** + * Get an excerpt of this entity's descriptive content to the specified length. + * @param int $length + * @return mixed + */ + public function getExcerpt(int $length = 100) + { + $text = $this->getText(); + if (mb_strlen($text) > $length) { + $text = mb_substr($text, 0, $length-3) . '...'; + } + return trim($text); + } + /** * Return a generalised, common raw query that can be 'unioned' across entities. * @return string diff --git a/app/Entities/EntityContextManager.php b/app/Entities/EntityContextManager.php new file mode 100644 index 00000000000..23ffed0d28c --- /dev/null +++ b/app/Entities/EntityContextManager.php @@ -0,0 +1,62 @@ +session = $session; + $this->entityRepo = $entityRepo; + } + + /** + * Get the current bookshelf context for the given book. + * @param Book $book + * @return Bookshelf|null + */ + public function getContextualShelfForBook(Book $book) + { + $contextBookshelfId = $this->session->get($this->KEY_SHELF_CONTEXT_ID, null); + if (is_int($contextBookshelfId)) { + + /** @var Bookshelf $shelf */ + $shelf = $this->entityRepo->getById('bookshelf', $contextBookshelfId); + + if ($shelf && $shelf->contains($book)) { + return $shelf; + } + + } + return null; + } + + /** + * Store the current contextual shelf ID. + * @param int $shelfId + */ + public function setShelfContext(int $shelfId) + { + $this->session->put($this->KEY_SHELF_CONTEXT_ID, $shelfId); + } + + /** + * Clear the session stored shelf context id. + */ + public function clearShelfContext() + { + $this->session->forget($this->KEY_SHELF_CONTEXT_ID); + } + +} \ No newline at end of file diff --git a/app/Entities/EntityProvider.php b/app/Entities/EntityProvider.php index 04939a14a41..d0d4a7ad6c0 100644 --- a/app/Entities/EntityProvider.php +++ b/app/Entities/EntityProvider.php @@ -84,4 +84,23 @@ public function get(string $type) $type = strtolower($type); return $this->all()[$type]; } + + /** + * Get the morph classes, as an array, for a single or multiple types. + * @param string|array $types + * @return array + */ + public function getMorphClasses($types) + { + if (is_string($types)) { + $types = [$types]; + } + + $morphClasses = []; + foreach ($types as $type) { + $model = $this->get($type); + $morphClasses[] = $model->getMorphClass(); + } + return $morphClasses; + } } diff --git a/app/Entities/Page.php b/app/Entities/Page.php index ea7df16f402..1c2cc5cff69 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -102,17 +102,6 @@ public function getUrl($path = false) return baseUrl('/books/' . urlencode($bookSlug) . $midText . $idComponent); } - /** - * Get an excerpt of this page's content to the specified length. - * @param int $length - * @return mixed - */ - public function getExcerpt($length = 100) - { - $text = strlen($this->text) > $length ? substr($this->text, 0, $length-3) . '...' : $this->text; - return mb_convert_encoding($text, 'UTF-8'); - } - /** * Return a generalised, common raw query that can be 'unioned' across entities. * @param bool $withContent diff --git a/app/Entities/PageRevision.php b/app/Entities/PageRevision.php index d30147bfc52..acdec2802bc 100644 --- a/app/Entities/PageRevision.php +++ b/app/Entities/PageRevision.php @@ -62,4 +62,5 @@ public static function isA($type) { return $type === 'revision'; } + } diff --git a/app/Entities/Repos/EntityRepo.php b/app/Entities/Repos/EntityRepo.php index 576ed70f00b..6fc2689a51b 100644 --- a/app/Entities/Repos/EntityRepo.php +++ b/app/Entities/Repos/EntityRepo.php @@ -15,6 +15,7 @@ use BookStack\Exceptions\NotifyException; use BookStack\Uploads\AttachmentService; use DOMDocument; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Collection; @@ -179,11 +180,38 @@ public function getAll($type, $count = 20, $permission = 'view') * Get all entities in a paginated format * @param $type * @param int $count + * @param string $sort + * @param string $order + * @param null|callable $queryAddition * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ - public function getAllPaginated($type, $count = 10) + public function getAllPaginated($type, int $count = 10, string $sort = 'name', string $order = 'asc', $queryAddition = null) { - return $this->entityQuery($type)->orderBy('name', 'asc')->paginate($count); + $query = $this->entityQuery($type); + $query = $this->addSortToQuery($query, $sort, $order); + if ($queryAddition) { + $queryAddition($query); + } + return $query->paginate($count); + } + + /** + * Add sorting operations to an entity query. + * @param Builder $query + * @param string $sort + * @param string $order + * @return Builder + */ + protected function addSortToQuery(Builder $query, string $sort = 'name', string $order = 'asc') + { + $order = ($order === 'asc') ? 'asc' : 'desc'; + $propertySorts = ['name', 'created_at', 'updated_at']; + + if (in_array($sort, $propertySorts)) { + return $query->orderBy($sort, $order); + } + + return $query; } /** @@ -265,15 +293,14 @@ public function getRecentlyUpdatedPaginated($type, $count = 20) /** * Get the most popular entities base on all views. - * @param string|bool $type + * @param string $type * @param int $count * @param int $page * @return mixed */ - public function getPopular($type, $count = 10, $page = 0) + public function getPopular(string $type, int $count = 10, int $page = 0) { - $filter = is_bool($type) ? false : $this->entityProvider->get($type); - return $this->viewService->getPopular($count, $page, $filter); + return $this->viewService->getPopular($count, $page, $type); } /** @@ -313,6 +340,18 @@ public function getBookshelfChildren(Bookshelf $bookshelf) return $this->permissionService->enforceEntityRestrictions('book', $bookshelf->books())->get(); } + /** + * Get the direct children of a book. + * @param Book $book + * @return \Illuminate\Database\Eloquent\Collection + */ + public function getBookDirectChildren(Book $book) + { + $pages = $this->permissionService->enforceEntityRestrictions('page', $book->directPages())->get(); + $chapters = $this->permissionService->enforceEntityRestrictions('chapters', $book->chapters())->get(); + return collect()->concat($pages)->concat($chapters)->sortBy('priority')->sortByDesc('draft'); + } + /** * Get all child objects of a book. * Returns a sorted collection of Pages and Chapters. diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e820154e71b..78a8d33c0ae 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -128,7 +128,7 @@ public function getLogin(Request $request) ]); } - return view('auth/login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); + return view('auth.login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); } /** diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index cdcca116ccd..da4f42bb106 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -176,7 +176,7 @@ protected function registerUser(array $userData, $socialAccount = false, $emailV */ public function getRegisterConfirmation() { - return view('auth/register-confirm'); + return view('auth.register-confirm'); } /** @@ -204,7 +204,7 @@ public function confirmEmail($token) */ public function showAwaitingConfirmation() { - return view('auth/user-unconfirmed'); + return view('auth.user-unconfirmed'); } /** diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 44368a9c4fb..9eb19ce6553 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -3,6 +3,7 @@ use Activity; use BookStack\Auth\UserRepo; use BookStack\Entities\Book; +use BookStack\Entities\EntityContextManager; use BookStack\Entities\Repos\EntityRepo; use BookStack\Entities\ExportService; use Illuminate\Http\Request; @@ -15,18 +16,25 @@ class BookController extends Controller protected $entityRepo; protected $userRepo; protected $exportService; + protected $entityContextManager; /** * BookController constructor. * @param EntityRepo $entityRepo - * @param \BookStack\Auth\UserRepo $userRepo - * @param \BookStack\Entities\ExportService $exportService + * @param UserRepo $userRepo + * @param ExportService $exportService + * @param EntityContextManager $entityContextManager */ - public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService) - { + public function __construct( + EntityRepo $entityRepo, + UserRepo $userRepo, + ExportService $exportService, + EntityContextManager $entityContextManager + ) { $this->entityRepo = $entityRepo; $this->userRepo = $userRepo; $this->exportService = $exportService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } @@ -36,18 +44,32 @@ public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportSe */ public function index() { - $books = $this->entityRepo->getAllPaginated('book', 18); + $view = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books')); + $sort = setting()->getUser($this->currentUser, 'books_sort', 'name'); + $order = setting()->getUser($this->currentUser, 'books_sort_order', 'asc'); + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $books = $this->entityRepo->getAllPaginated('book', 18, $sort, $order); $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('book', 4, 0) : false; $popular = $this->entityRepo->getPopular('book', 4, 0); $new = $this->entityRepo->getRecentlyCreated('book', 4, 0); - $booksViewType = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books', 'list')); + + $this->entityContextManager->clearShelfContext(); + $this->setPageTitle(trans('entities.books')); - return view('books/index', [ + return view('books.index', [ 'books' => $books, 'recents' => $recents, 'popular' => $popular, 'new' => $new, - 'booksViewType' => $booksViewType + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, ]); } @@ -59,7 +81,7 @@ public function create() { $this->checkPermission('book-create-all'); $this->setPageTitle(trans('entities.books_create')); - return view('books/create'); + return view('books.create'); } /** @@ -83,20 +105,28 @@ public function store(Request $request) /** * Display the specified book. * @param $slug + * @param Request $request * @return Response + * @throws \BookStack\Exceptions\NotFoundException */ - public function show($slug) + public function show($slug, Request $request) { $book = $this->entityRepo->getBySlug('book', $slug); $this->checkOwnablePermission('book-view', $book); + $bookChildren = $this->entityRepo->getBookChildren($book); + Views::add($book); + if ($request->has('shelf')) { + $this->entityContextManager->setShelfContext(intval($request->get('shelf'))); + } + $this->setPageTitle($book->getShortName()); - return view('books/show', [ + return view('books.show', [ 'book' => $book, 'current' => $book, 'bookChildren' => $bookChildren, - 'activity' => Activity::entityActivity($book, 20, 0) + 'activity' => Activity::entityActivity($book, 20, 1) ]); } @@ -110,7 +140,7 @@ public function edit($slug) $book = $this->entityRepo->getBySlug('book', $slug); $this->checkOwnablePermission('book-update', $book); $this->setPageTitle(trans('entities.books_edit_named', ['bookName'=>$book->getShortName()])); - return view('books/edit', ['book' => $book, 'current' => $book]); + return view('books.edit', ['book' => $book, 'current' => $book]); } /** @@ -142,22 +172,24 @@ public function showDelete($bookSlug) $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('book-delete', $book); $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()])); - return view('books/delete', ['book' => $book, 'current' => $book]); + return view('books.delete', ['book' => $book, 'current' => $book]); } /** * Shows the view which allows pages to be re-ordered and sorted. * @param string $bookSlug * @return \Illuminate\View\View + * @throws \BookStack\Exceptions\NotFoundException */ public function sort($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('book-update', $book); + $bookChildren = $this->entityRepo->getBookChildren($book, true); - $books = $this->entityRepo->getAll('book', false, 'update'); + $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()])); - return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]); + return view('books.sort', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]); } /** @@ -170,7 +202,7 @@ public function getSortItem($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $bookChildren = $this->entityRepo->getBookChildren($book); - return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]); + return view('books.sort-box', ['book' => $book, 'bookChildren' => $bookChildren]); } /** @@ -263,12 +295,12 @@ public function destroy($bookSlug) * @param $bookSlug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function showRestrict($bookSlug) + public function showPermissions($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('restrictions-manage', $book); $roles = $this->userRepo->getRestrictableRoles(); - return view('books/restrictions', [ + return view('books.permissions', [ 'book' => $book, 'roles' => $roles ]); @@ -277,11 +309,12 @@ public function showRestrict($bookSlug) /** * Set the restrictions for this book. * @param $bookSlug - * @param $bookSlug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, Request $request) + public function permissions($bookSlug, Request $request) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('restrictions-manage', $book); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index 5c2898786f0..b86bc2e38d9 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -3,8 +3,8 @@ use Activity; use BookStack\Auth\UserRepo; use BookStack\Entities\Bookshelf; +use BookStack\Entities\EntityContextManager; use BookStack\Entities\Repos\EntityRepo; -use BookStack\Entities\ExportService; use Illuminate\Http\Request; use Illuminate\Http\Response; use Views; @@ -14,19 +14,19 @@ class BookshelfController extends Controller protected $entityRepo; protected $userRepo; - protected $exportService; + protected $entityContextManager; /** * BookController constructor. - * @param \BookStack\Entities\Repos\EntityRepo $entityRepo + * @param EntityRepo $entityRepo * @param UserRepo $userRepo - * @param \BookStack\Entities\ExportService $exportService + * @param EntityContextManager $entityContextManager */ - public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService) + public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, EntityContextManager $entityContextManager) { $this->entityRepo = $entityRepo; $this->userRepo = $userRepo; - $this->exportService = $exportService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } @@ -36,19 +36,35 @@ public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportSe */ public function index() { - $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18); + $view = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); + $sort = setting()->getUser($this->currentUser, 'bookshelves_sort', 'name'); + $order = setting()->getUser($this->currentUser, 'bookshelves_sort_order', 'asc'); + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18, $sort, $order); + foreach ($shelves as $shelf) { + $shelf->books = $this->entityRepo->getBookshelfChildren($shelf); + } + $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('bookshelf', 4, 0) : false; $popular = $this->entityRepo->getPopular('bookshelf', 4, 0); $new = $this->entityRepo->getRecentlyCreated('bookshelf', 4, 0); - $shelvesViewType = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); + $this->entityContextManager->clearShelfContext(); $this->setPageTitle(trans('entities.shelves')); - return view('shelves/index', [ + return view('shelves.index', [ 'shelves' => $shelves, 'recents' => $recents, 'popular' => $popular, 'new' => $new, - 'shelvesViewType' => $shelvesViewType + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, ]); } @@ -61,7 +77,7 @@ public function create() $this->checkPermission('bookshelf-create-all'); $books = $this->entityRepo->getAll('book', false, 'update'); $this->setPageTitle(trans('entities.shelves_create')); - return view('shelves/create', ['books' => $books]); + return view('shelves.create', ['books' => $books]); } /** @@ -93,17 +109,19 @@ public function store(Request $request) */ public function show(string $slug) { - $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); /** @var $bookshelf Bookshelf */ + /** @var Bookshelf $bookshelf */ + $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('book-view', $bookshelf); $books = $this->entityRepo->getBookshelfChildren($bookshelf); Views::add($bookshelf); + $this->entityContextManager->setShelfContext($bookshelf->id); $this->setPageTitle($bookshelf->getShortName()); - return view('shelves/show', [ + return view('shelves.show', [ 'shelf' => $bookshelf, 'books' => $books, - 'activity' => Activity::entityActivity($bookshelf, 20, 0) + 'activity' => Activity::entityActivity($bookshelf, 20, 1) ]); } @@ -126,7 +144,7 @@ public function edit(string $slug) }); $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $bookshelf->getShortName()])); - return view('shelves/edit', [ + return view('shelves.edit', [ 'shelf' => $bookshelf, 'books' => $books, 'shelfBooks' => $shelfBooks, @@ -170,7 +188,7 @@ public function showDelete(string $slug) $this->checkOwnablePermission('bookshelf-delete', $bookshelf); $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $bookshelf->getShortName()])); - return view('shelves/delete', ['shelf' => $bookshelf]); + return view('shelves.delete', ['shelf' => $bookshelf]); } /** @@ -190,31 +208,32 @@ public function destroy(string $slug) } /** - * Show the Restrictions view. - * @param $slug + * Show the permissions view. + * @param string $slug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @throws \BookStack\Exceptions\NotFoundException */ - public function showRestrict(string $slug) + public function showPermissions(string $slug) { $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('restrictions-manage', $bookshelf); $roles = $this->userRepo->getRestrictableRoles(); - return view('shelves.restrictions', [ + return view('shelves.permissions', [ 'shelf' => $bookshelf, 'roles' => $roles ]); } /** - * Set the restrictions for this bookshelf. - * @param $slug + * Set the permissions for this bookshelf. + * @param string $slug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict(string $slug, Request $request) + public function permissions(string $slug, Request $request) { $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('restrictions-manage', $bookshelf); diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index 20ab9613318..c19e4569485 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -39,7 +39,7 @@ public function create($bookSlug) $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('chapter-create', $book); $this->setPageTitle(trans('entities.chapters_create')); - return view('chapters/create', ['book' => $book, 'current' => $book]); + return view('chapters.create', ['book' => $book, 'current' => $book]); } /** @@ -78,7 +78,7 @@ public function show($bookSlug, $chapterSlug) Views::add($chapter); $this->setPageTitle($chapter->getShortName()); $pages = $this->entityRepo->getChapterChildren($chapter); - return view('chapters/show', [ + return view('chapters.show', [ 'book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter, @@ -98,7 +98,7 @@ public function edit($bookSlug, $chapterSlug) $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('chapter-update', $chapter); $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()])); - return view('chapters/edit', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); + return view('chapters.edit', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); } /** @@ -130,7 +130,7 @@ public function showDelete($bookSlug, $chapterSlug) $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('chapter-delete', $chapter); $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()])); - return view('chapters/delete', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); + return view('chapters.delete', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); } /** @@ -162,7 +162,7 @@ public function showMove($bookSlug, $chapterSlug) $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()])); $this->checkOwnablePermission('chapter-update', $chapter); $this->checkOwnablePermission('chapter-delete', $chapter); - return view('chapters/move', [ + return view('chapters.move', [ 'chapter' => $chapter, 'book' => $chapter->book ]); @@ -214,13 +214,14 @@ public function move($bookSlug, $chapterSlug, Request $request) * @param $bookSlug * @param $chapterSlug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \BookStack\Exceptions\NotFoundException */ - public function showRestrict($bookSlug, $chapterSlug) + public function showPermissions($bookSlug, $chapterSlug) { $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $chapter); $roles = $this->userRepo->getRestrictableRoles(); - return view('chapters/restrictions', [ + return view('chapters.permissions', [ 'chapter' => $chapter, 'roles' => $roles ]); @@ -232,8 +233,10 @@ public function showRestrict($bookSlug, $chapterSlug) * @param $chapterSlug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, $chapterSlug, Request $request) + public function permissions($bookSlug, $chapterSlug, Request $request) { $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $chapter); diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 2039ce7fe9f..860b507623f 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -54,7 +54,7 @@ public function savePageComment(Request $request, $pageId, $commentId = null) $this->checkPermission('comment-create-all'); $comment = $this->commentRepo->create($page, $request->only(['html', 'text', 'parent_id'])); Activity::add($page, 'commented_on', $page->book->id); - return view('comments/comment', ['comment' => $comment]); + return view('comments.comment', ['comment' => $comment]); } /** @@ -75,7 +75,7 @@ public function update(Request $request, $commentId) $this->checkOwnablePermission('comment-update', $comment); $comment = $this->commentRepo->update($comment, $request->only(['html', 'text'])); - return view('comments/comment', ['comment' => $comment]); + return view('comments.comment', ['comment' => $comment]); } /** diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 80f567eaa80..fc4f184fcab 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -123,6 +123,20 @@ protected function checkPermissionOr($permissionName, $callback) return true; } + /** + * Check if the current user has a permission or bypass if the provided user + * id matches the current user. + * @param string $permissionName + * @param int $userId + * @return bool + */ + protected function checkPermissionOrCurrentUser(string $permissionName, int $userId) + { + return $this->checkPermissionOr($permissionName, function() use ($userId) { + return $userId === $this->currentUser->id; + }); + } + /** * Send back a json error message. * @param string $messageText diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 5a5f34e4a5c..c5f3cd02a4b 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -19,7 +19,6 @@ public function __construct(EntityRepo $entityRepo) parent::__construct(); } - /** * Display the homepage. * @return Response @@ -45,17 +44,36 @@ public function index() 'draftPages' => $draftPages, ]; + // Add required list ordering & sorting for books & shelves views. + if ($homepageOption === 'bookshelves' || $homepageOption === 'books') { + $key = $homepageOption; + $view = setting()->getUser($this->currentUser, $key . '_view_type', config('app.views.' . $key)); + $sort = setting()->getUser($this->currentUser, $key . '_sort', 'name'); + $order = setting()->getUser($this->currentUser, $key . '_sort_order', 'asc'); + + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $commonData = array_merge($commonData, [ + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, + ]); + } + if ($homepageOption === 'bookshelves') { - $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18); - $shelvesViewType = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); - $data = array_merge($commonData, ['shelves' => $shelves, 'shelvesViewType' => $shelvesViewType]); + $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18, $commonData['sort'], $commonData['order']); + $data = array_merge($commonData, ['shelves' => $shelves]); return view('common.home-shelves', $data); } if ($homepageOption === 'books') { - $books = $this->entityRepo->getAllPaginated('book', 18); - $booksViewType = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books', 'list')); - $data = array_merge($commonData, ['books' => $books, 'booksViewType' => $booksViewType]); + $books = $this->entityRepo->getAllPaginated('book', 18, $commonData['sort'], $commonData['order']); + $data = array_merge($commonData, ['books' => $books]); return view('common.home-book', $data); } @@ -105,7 +123,7 @@ public function getTranslations() */ public function customHeadContent() { - return view('partials/custom-head-content'); + return view('partials.custom-head-content'); } /** @@ -120,7 +138,7 @@ public function getRobots() $allowRobots = $sitePublic; } return response() - ->view('common/robots', ['allowRobots' => $allowRobots]) + ->view('common.robots', ['allowRobots' => $allowRobots]) ->header('Content-Type', 'text/plain'); } @@ -129,6 +147,6 @@ public function getRobots() */ public function getNotFound() { - return response()->view('errors/404', [], 404); + return response()->view('errors.404', [], 404); } } diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index d95e02470be..16a7d5a5e45 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -61,7 +61,7 @@ public function create($bookSlug, $chapterSlug = null) // Otherwise show the edit view if they're a guest $this->setPageTitle(trans('entities.pages_new')); - return view('pages/guest-create', ['parent' => $parent]); + return view('pages.guest-create', ['parent' => $parent]); } /** @@ -110,7 +110,7 @@ public function editDraft($bookSlug, $pageId) $this->setPageTitle(trans('entities.pages_edit_draft')); $draftsEnabled = $this->signedIn; - return view('pages/edit', [ + return view('pages.edit', [ 'page' => $draft, 'book' => $draft->book, 'isDraft' => true, @@ -184,7 +184,7 @@ public function show($bookSlug, $pageSlug) Views::add($page); $this->setPageTitle($page->getShortName()); - return view('pages/show', [ + return view('pages.show', [ 'page' => $page,'book' => $page->book, 'current' => $page, 'sidebarTree' => $sidebarTree, @@ -239,7 +239,7 @@ public function edit($bookSlug, $pageSlug) } $draftsEnabled = $this->signedIn; - return view('pages/edit', [ + return view('pages.edit', [ 'page' => $page, 'book' => $page->book, 'current' => $page, @@ -317,7 +317,7 @@ public function showDelete($bookSlug, $pageSlug) $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-delete', $page); $this->setPageTitle(trans('entities.pages_delete_named', ['pageName'=>$page->getShortName()])); - return view('pages/delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); + return view('pages.delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); } @@ -333,7 +333,7 @@ public function showDeleteDraft($bookSlug, $pageId) $page = $this->pageRepo->getById('page', $pageId, true); $this->checkOwnablePermission('page-update', $page); $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName'=>$page->getShortName()])); - return view('pages/delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); + return view('pages.delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); } /** @@ -377,12 +377,13 @@ public function destroyDraft($bookSlug, $pageId) * @param string $bookSlug * @param string $pageSlug * @return \Illuminate\View\View + * @throws NotFoundException */ public function showRevisions($bookSlug, $pageSlug) { $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName'=>$page->getShortName()])); - return view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); + return view('pages.revisions', ['page' => $page, 'current' => $page]); } /** @@ -403,9 +404,10 @@ public function showRevision($bookSlug, $pageSlug, $revisionId) $page->fill($revision->toArray()); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()])); - return view('pages/revision', [ + return view('pages.revision', [ 'page' => $page, 'book' => $page->book, + 'diff' => null, 'revision' => $revision ]); } @@ -432,7 +434,7 @@ public function showRevisionChanges($bookSlug, $pageSlug, $revisionId) $page->fill($revision->toArray()); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()])); - return view('pages/revision', [ + return view('pages.revision', [ 'page' => $page, 'book' => $page->book, 'diff' => $diff, @@ -482,12 +484,12 @@ public function destroyRevision($bookSlug, $pageSlug, $revId) // Check if its the latest revision, cannot delete latest revision. if (intval($currentRevision->id) === intval($revId)) { session()->flash('error', trans('entities.revision_cannot_delete_latest')); - return response()->view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page], 400); + return response()->view('pages.revisions', ['page' => $page, 'book' => $page->book, 'current' => $page], 400); } $revision->delete(); session()->flash('success', trans('entities.revision_delete_success')); - return view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); + return view('pages.revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); } /** @@ -532,49 +534,20 @@ public function exportPlainText($bookSlug, $pageSlug) return $this->downloadResponse($pageText, $pageSlug . '.txt'); } - /** - * Show a listing of recently created pages - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - */ - public function showRecentlyCreated() - { - $pages = $this->pageRepo->getRecentlyCreatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-created')); - return view('pages/detailed-listing', [ - 'title' => trans('entities.recently_created_pages'), - 'pages' => $pages - ]); - } - /** * Show a listing of recently created pages * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showRecentlyUpdated() { + // TODO - Still exist? $pages = $this->pageRepo->getRecentlyUpdatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-updated')); - return view('pages/detailed-listing', [ + return view('pages.detailed-listing', [ 'title' => trans('entities.recently_updated_pages'), 'pages' => $pages ]); } - /** - * Show the Restrictions view. - * @param string $bookSlug - * @param string $pageSlug - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - */ - public function showRestrict($bookSlug, $pageSlug) - { - $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); - $this->checkOwnablePermission('restrictions-manage', $page); - $roles = $this->userRepo->getRestrictableRoles(); - return view('pages/restrictions', [ - 'page' => $page, - 'roles' => $roles - ]); - } - /** * Show the view to choose a new parent to move a page into. * @param string $bookSlug @@ -587,7 +560,7 @@ public function showMove($bookSlug, $pageSlug) $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-update', $page); $this->checkOwnablePermission('page-delete', $page); - return view('pages/move', [ + return view('pages.move', [ 'book' => $page->book, 'page' => $page ]); @@ -645,7 +618,7 @@ public function showCopy($bookSlug, $pageSlug) $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-view', $page); session()->flashInput(['name' => $page->name]); - return view('pages/copy', [ + return view('pages.copy', [ 'book' => $page->book, 'page' => $page ]); @@ -690,6 +663,24 @@ public function copy($bookSlug, $pageSlug, Request $request) return redirect($pageCopy->getUrl()); } + /** + * Show the Permissions view. + * @param string $bookSlug + * @param string $pageSlug + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws NotFoundException + */ + public function showPermissions($bookSlug, $pageSlug) + { + $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); + $this->checkOwnablePermission('restrictions-manage', $page); + $roles = $this->userRepo->getRestrictableRoles(); + return view('pages.permissions', [ + 'page' => $page, + 'roles' => $roles + ]); + } + /** * Set the permissions for this page. * @param string $bookSlug @@ -697,8 +688,9 @@ public function copy($bookSlug, $pageSlug, Request $request) * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, $pageSlug, Request $request) + public function permissions($bookSlug, $pageSlug, Request $request) { $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $page); diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php index 9be343c9a76..9893d59935f 100644 --- a/app/Http/Controllers/PermissionController.php +++ b/app/Http/Controllers/PermissionController.php @@ -26,7 +26,7 @@ public function listRoles() { $this->checkPermission('user-roles-manage'); $roles = $this->permissionsRepo->getAllRoles(); - return view('settings/roles/index', ['roles' => $roles]); + return view('settings.roles.index', ['roles' => $roles]); } /** @@ -36,7 +36,7 @@ public function listRoles() public function createRole() { $this->checkPermission('user-roles-manage'); - return view('settings/roles/create'); + return view('settings.roles.create'); } /** @@ -70,7 +70,7 @@ public function editRole($id) if ($role->hidden) { throw new PermissionsException(trans('errors.role_cannot_be_edited')); } - return view('settings/roles/edit', ['role' => $role]); + return view('settings.roles.edit', ['role' => $role]); } /** @@ -106,7 +106,7 @@ public function showDeleteRole($id) $roles = $this->permissionsRepo->getAllRolesExcept($role); $blankRole = $role->newInstance(['display_name' => trans('settings.role_delete_no_migration')]); $roles->prepend($blankRole); - return view('settings/roles/delete', ['role' => $role, 'roles' => $roles]); + return view('settings.roles.delete', ['role' => $role, 'roles' => $roles]); } /** diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index d8f2dc4d7ea..4bcf7b40eff 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -1,34 +1,45 @@ entityRepo = $entityRepo; $this->viewService = $viewService; $this->searchService = $searchService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } /** * Searches all entities. * @param Request $request - * @return \Illuminate\View\View + * @return View * @internal param string $searchTerm */ public function search(Request $request) @@ -41,7 +52,7 @@ public function search(Request $request) $results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20); - return view('search/all', [ + return view('search.all', [ 'entities' => $results['results'], 'totalResults' => $results['total'], 'searchTerm' => $searchTerm, @@ -55,28 +66,28 @@ public function search(Request $request) * Searches all entities within a book. * @param Request $request * @param integer $bookId - * @return \Illuminate\View\View + * @return View * @internal param string $searchTerm */ public function searchBook(Request $request, $bookId) { $term = $request->get('term', ''); $results = $this->searchService->searchBook($bookId, $term); - return view('partials/entity-list', ['entities' => $results]); + return view('partials.entity-list', ['entities' => $results]); } /** * Searches all entities within a chapter. * @param Request $request * @param integer $chapterId - * @return \Illuminate\View\View + * @return View * @internal param string $searchTerm */ public function searchChapter(Request $request, $chapterId) { $term = $request->get('term', ''); $results = $this->searchService->searchChapter($chapterId, $term); - return view('partials/entity-list', ['entities' => $results]); + return view('partials.entity-list', ['entities' => $results]); } /** @@ -87,21 +98,64 @@ public function searchChapter(Request $request, $chapterId) */ public function searchEntitiesAjax(Request $request) { - $entityTypes = $request->filled('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']); + $entityTypes = $request->filled('types') ? explode(',', $request->get('types')) : ['page', 'chapter', 'book']; $searchTerm = $request->get('term', false); $permission = $request->get('permission', 'view'); // Search for entities otherwise show most popular if ($searchTerm !== false) { - $searchTerm .= ' {type:'. implode('|', $entityTypes->toArray()) .'}'; + $searchTerm .= ' {type:'. implode('|', $entityTypes) .'}'; $entities = $this->searchService->searchEntities($searchTerm, 'all', 1, 20, $permission)['results']; } else { - $entityNames = $entityTypes->map(function ($type) { - return 'BookStack\\' . ucfirst($type); // TODO - Extract this elsewhere, too specific and stringy - })->toArray(); - $entities = $this->viewService->getPopular(20, 0, $entityNames, $permission); + $entities = $this->viewService->getPopular(20, 0, $entityTypes, $permission); + } + + return view('search.entity-ajax-list', ['entities' => $entities]); + } + + /** + * Search siblings items in the system. + * @param Request $request + * @return Factory|View|mixed + */ + public function searchSiblings(Request $request) + { + $type = $request->get('entity_type', null); + $id = $request->get('entity_id', null); + + $entity = $this->entityRepo->getById($type, $id); + if (!$entity) { + return $this->jsonError(trans('errors.entity_not_found'), 404); + } + + $entities = []; + + // Page in chapter + if ($entity->isA('page') && $entity->chapter) { + $entities = $this->entityRepo->getChapterChildren($entity->chapter); + } + + // Page in book or chapter + if (($entity->isA('page') && !$entity->chapter) || $entity->isA('chapter')) { + $entities = $this->entityRepo->getBookDirectChildren($entity->book); + } + + // Book + // Gets just the books in a shelf if shelf is in context + if ($entity->isA('book')) { + $contextShelf = $this->entityContextManager->getContextualShelfForBook($entity); + if ($contextShelf) { + $entities = $this->entityRepo->getBookshelfChildren($contextShelf); + } else { + $entities = $this->entityRepo->getAll('book'); + } + } + + // Shelve + if ($entity->isA('bookshelf')) { + $entities = $this->entityRepo->getAll('bookshelf'); } - return view('search/entity-ajax-list', ['entities' => $entities]); + return view('partials.entity-list-basic', ['entities' => $entities, 'style' => 'compact']); } } diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 01fb68fe06e..159e19a2bb4 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -1,5 +1,6 @@ $version]); + return view('settings.index', [ + 'version' => $version, + 'guestUser' => User::getDefault() + ]); } /** @@ -57,7 +61,7 @@ public function showMaintenance() // Get application version $version = trim(file_get_contents(base_path('version'))); - return view('settings/maintenance', ['version' => $version]); + return view('settings.maintenance', ['version' => $version]); } /** diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index cc5ada3f283..1bb5d46cdab 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -41,7 +41,7 @@ public function index(Request $request) $users = $this->userRepo->getAllUsersPaginatedAndSorted(20, $listDetails); $this->setPageTitle(trans('settings.users')); $users->appends($listDetails); - return view('users/index', ['users' => $users, 'listDetails' => $listDetails]); + return view('users.index', ['users' => $users, 'listDetails' => $listDetails]); } /** @@ -53,7 +53,7 @@ public function create() $this->checkPermission('users-manage'); $authMethod = config('auth.method'); $roles = $this->userRepo->getAllRoles(); - return view('users/create', ['authMethod' => $authMethod, 'roles' => $roles]); + return view('users.create', ['authMethod' => $authMethod, 'roles' => $roles]); } /** @@ -118,7 +118,7 @@ public function edit($id, SocialAuthService $socialAuthService) $activeSocialDrivers = $socialAuthService->getActiveDrivers(); $this->setPageTitle(trans('settings.user_profile')); $roles = $this->userRepo->getAllRoles(); - return view('users/edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); + return view('users.edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); } /** @@ -190,7 +190,7 @@ public function delete($id) $user = $this->userRepo->getById($id); $this->setPageTitle(trans('settings.users_delete_named', ['userName' => $user->name])); - return view('users/delete', ['user' => $user]); + return view('users.delete', ['user' => $user]); } /** @@ -232,10 +232,12 @@ public function destroy($id) public function showProfilePage($id) { $user = $this->userRepo->getById($id); + $userActivity = $this->userRepo->getActivity($user); $recentlyCreated = $this->userRepo->getRecentlyCreated($user, 5, 0); $assetCounts = $this->userRepo->getAssetCounts($user); - return view('users/profile', [ + + return view('users.profile', [ 'user' => $user, 'activity' => $userActivity, 'recentlyCreated' => $recentlyCreated, @@ -251,41 +253,109 @@ public function showProfilePage($id) */ public function switchBookView($id, Request $request) { - $this->checkPermissionOr('users-manage', function () use ($id) { - return $this->currentUser->id == $id; - }); + return $this->switchViewType($id, $request, 'books'); + } + + /** + * Update the user's preferred shelf-list display setting. + * @param $id + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function switchShelfView($id, Request $request) + { + return $this->switchViewType($id, $request, 'bookshelves'); + } + + /** + * For a type of list, switch with stored view type for a user. + * @param integer $userId + * @param Request $request + * @param string $listName + * @return \Illuminate\Http\RedirectResponse + */ + protected function switchViewType($userId, Request $request, string $listName) + { + $this->checkPermissionOrCurrentUser('users-manage', $userId); $viewType = $request->get('view_type'); if (!in_array($viewType, ['grid', 'list'])) { $viewType = 'list'; } - $user = $this->user->findOrFail($id); - setting()->putUser($user, 'books_view_type', $viewType); + $user = $this->userRepo->getById($userId); + $key = $listName . '_view_type'; + setting()->putUser($user, $key, $viewType); - return redirect()->back(302, [], "/settings/users/$id"); + return redirect()->back(302, [], "/settings/users/$userId"); } /** - * Update the user's preferred shelf-list display setting. - * @param $id + * Change the stored sort type for a particular view. + * @param string $id + * @param string $type * @param Request $request * @return \Illuminate\Http\RedirectResponse */ - public function switchShelfView($id, Request $request) + public function changeSort(string $id, string $type, Request $request) { - $this->checkPermissionOr('users-manage', function () use ($id) { - return $this->currentUser->id == $id; - }); + $validSortTypes = ['books', 'bookshelves']; + if (!in_array($type, $validSortTypes)) { + return redirect()->back(500); + } + return $this->changeListSort($id, $request, $type); + } - $viewType = $request->get('view_type'); - if (!in_array($viewType, ['grid', 'list'])) { - $viewType = 'list'; + /** + * Update the stored section expansion preference for the given user. + * @param string $id + * @param string $key + * @param Request $request + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response + */ + public function updateExpansionPreference(string $id, string $key, Request $request) + { + $this->checkPermissionOrCurrentUser('users-manage', $id); + $keyWhitelist = ['home-details']; + if (!in_array($key, $keyWhitelist)) { + return response("Invalid key", 500); } - $user = $this->userRepo->getById($id); - setting()->putUser($user, 'bookshelves_view_type', $viewType); + $newState = $request->get('expand', 'false'); - return redirect()->back(302, [], "/settings/users/$id"); + $user = $this->user->findOrFail($id); + setting()->putUser($user, 'section_expansion#' . $key, $newState); + return response("", 204); } + + /** + * Changed the stored preference for a list sort order. + * @param int $userId + * @param Request $request + * @param string $listName + * @return \Illuminate\Http\RedirectResponse + */ + protected function changeListSort(int $userId, Request $request, string $listName) + { + $this->checkPermissionOrCurrentUser('users-manage', $userId); + + $sort = $request->get('sort'); + if (!in_array($sort, ['name', 'created_at', 'updated_at'])) { + $sort = 'name'; + } + + $order = $request->get('order'); + if (!in_array($order, ['asc', 'desc'])) { + $order = 'asc'; + } + + $user = $this->user->findOrFail($userId); + $sortKey = $listName . '_sort'; + $orderKey = $listName . '_sort_order'; + setting()->putUser($user, $sortKey, $sort); + setting()->putUser($user, $orderKey, $order); + + return redirect()->back(302, [], "/settings/users/$userId"); + } + } diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index c9b2726e8c4..1a33843675a 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -37,7 +37,7 @@ public function handle($request, Closure $next) } } - if ($this->auth->guest() && !setting('app-public')) { + if (!hasAppAccess()) { if ($request->ajax()) { return response('Unauthorized.', 401); } else { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3ca59dcb334..9b91ba126c5 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,12 +3,14 @@ use Blade; use BookStack\Entities\Book; use BookStack\Entities\Bookshelf; +use BookStack\Entities\BreadcrumbsViewComposer; use BookStack\Entities\Chapter; use BookStack\Entities\Page; use BookStack\Settings\Setting; use BookStack\Settings\SettingService; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Http\UploadedFile; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Schema; use Validator; @@ -33,7 +35,6 @@ public function boot() return substr_count($uploadName, '.') < 2; }); - // Custom blade view directives Blade::directive('icon', function ($expression) { return ""; @@ -49,6 +50,9 @@ public function boot() 'BookStack\\Chapter' => Chapter::class, 'BookStack\\Page' => Page::class, ]); + + // View Composers + View::composer('partials.breadcrumbs', BreadcrumbsViewComposer::class); } /** diff --git a/app/Providers/CustomFacadeProvider.php b/app/Providers/CustomFacadeProvider.php index 5508ee9cd3e..e7bde529049 100644 --- a/app/Providers/CustomFacadeProvider.php +++ b/app/Providers/CustomFacadeProvider.php @@ -2,20 +2,11 @@ namespace BookStack\Providers; -use BookStack\Actions\Activity; use BookStack\Actions\ActivityService; -use BookStack\Actions\View; use BookStack\Actions\ViewService; -use BookStack\Auth\Permissions\PermissionService; -use BookStack\Settings\Setting; use BookStack\Settings\SettingService; -use BookStack\Uploads\HttpFetcher; -use BookStack\Uploads\Image; use BookStack\Uploads\ImageService; -use Illuminate\Contracts\Cache\Repository; -use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Support\ServiceProvider; -use Intervention\Image\ImageManager; class CustomFacadeProvider extends ServiceProvider { @@ -37,34 +28,19 @@ public function boot() public function register() { $this->app->bind('activity', function () { - return new ActivityService( - $this->app->make(Activity::class), - $this->app->make(PermissionService::class) - ); + return $this->app->make(ActivityService::class); }); $this->app->bind('views', function () { - return new ViewService( - $this->app->make(View::class), - $this->app->make(PermissionService::class) - ); + return $this->app->make(ViewService::class); }); $this->app->bind('setting', function () { - return new SettingService( - $this->app->make(Setting::class), - $this->app->make(Repository::class) - ); + return $this->app->make(SettingService::class); }); $this->app->bind('images', function () { - return new ImageService( - $this->app->make(Image::class), - $this->app->make(ImageManager::class), - $this->app->make(Factory::class), - $this->app->make(Repository::class), - $this->app->make(HttpFetcher::class) - ); + return $this->app->make(ImageService::class); }); } } diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index c9491e3eeb4..489963aad7c 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -61,9 +61,23 @@ public function get($key, $default = false) */ public function getUser($user, $key, $default = false) { + if ($user->isDefault()) { + return session()->get($key, $default); + } return $this->get($this->userKey($user->id, $key), $default); } + /** + * Get a value for the current logged-in user. + * @param $key + * @param bool $default + * @return bool|string + */ + public function getForCurrentUser($key, $default = false) + { + return $this->getUser(user(), $key, $default); + } + /** * Gets a setting value from the cache or database. * Looks at the system defaults if not cached or in database. @@ -180,6 +194,9 @@ public function put($key, $value) */ public function putUser($user, $key, $value) { + if ($user->isDefault()) { + return session()->put($key, $value); + } return $this->put($this->userKey($user->id, $key), $value); } diff --git a/app/helpers.php b/app/helpers.php index d9533645de6..3f7b5e1b135 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -43,11 +43,19 @@ function user() * Check if current user is a signed in user. * @return bool */ -function signedInUser() +function signedInUser() : bool { return auth()->user() && !auth()->user()->isDefault(); } +/** + * Check if the current user has general access. + * @return bool + */ +function hasAppAccess() : bool { + return !auth()->guest() || setting('app-public'); +} + /** * Check if the current user has a permission. * If an ownable element is passed in the jointPermissions are checked against diff --git a/package-lock.json b/package-lock.json index e1d1ace438c..1a5fef175c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -981,12 +981,6 @@ "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -1176,27 +1170,49 @@ "dev": true }, "autoprefixer": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", - "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "version": "9.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.7.tgz", + "integrity": "sha512-qS5wW6aXHkm53Y4z73tFGsUhmZu4aMPV9iHXYlF0c/wxjknXNHuj/1cIQb+6YH692DbJGGWcckAXX+VxKvahMA==", "dev": true, "requires": { - "browserslist": "^3.2.8", - "caniuse-lite": "^1.0.30000864", + "browserslist": "^4.4.1", + "caniuse-lite": "^1.0.30000932", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^6.0.23", - "postcss-value-parser": "^3.2.3" + "postcss": "^7.0.14", + "postcss-value-parser": "^3.3.1" }, "dependencies": { "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" + } + }, + "caniuse-lite": { + "version": "1.0.30000934", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000934.tgz", + "integrity": "sha512-o7yfZn0R9N+mWAuksDsdLsb1gu9o//XK0QSU0zSSReKNRsXsFc/n/psxi0YSPNiqlKxImp5h4DHnAPdwYJ8nNA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.112", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.112.tgz", + "integrity": "sha512-FyVLdiRZnLw2WE5ECtveN0JJ7klyiz/HMfKE1/Rjff3l7pe4vfkYtBlcCqTckvR8E7asjJGh0m9gRPR3Anp/UA==", + "dev": true + }, + "node-releases": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz", + "integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "semver": "^5.3.0" } } } @@ -1240,50 +1256,6 @@ } } }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "babel-loader": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.4.tgz", @@ -1570,31 +1542,59 @@ "dev": true }, "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" }, "dependencies": { + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -1639,36 +1639,6 @@ "map-obj": "^1.0.0" } }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - } - } - }, - "caniuse-db": { - "version": "1.0.30000904", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000904.tgz", - "integrity": "sha512-iZ36AxtEx7ZiCBKhF2qFL8ED6u9zJGPU7Aq6HwZQYUbetBgYkGZfoPHq9z38jahV2kr8BgDYfXvftA35Ng2AaA==", - "dev": true - }, "caniuse-lite": { "version": "1.0.30000904", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000904.tgz", @@ -1734,42 +1704,6 @@ "safe-buffer": "^5.0.1" } }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "dev": true, - "requires": { - "chalk": "^1.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1820,12 +1754,6 @@ "wrap-ansi": "^2.0.0" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, "clone-deep": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", @@ -1861,15 +1789,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "^1.1.2" - } - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1891,17 +1810,6 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1917,32 +1825,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "^0.11.0", - "css-color-names": "0.0.4", - "has": "^1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -1953,9 +1835,9 @@ } }, "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true }, "commondir": { @@ -2062,22 +1944,6 @@ "require-from-string": "^2.0.1" }, "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -2156,92 +2022,95 @@ "randomfill": "^1.0.3" } }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, "css-loader": { - "version": "0.28.11", - "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", - "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "cssnano": "^3.10.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", - "object-assign": "^4.1.1", - "postcss": "^5.0.6", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.0.tgz", + "integrity": "sha512-MoOu+CStsGrSt5K2OeZ89q3Snf+IkxRfAIt9aAKg4piioTrhtP1iEFPu+OVn3Ohz24FO6L+rw9UJxBILiSBw5Q==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "loader-utils": "^1.2.1", + "lodash": "^4.17.11", + "postcss": "^7.0.6", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.3", + "postcss-modules-scope": "^2.0.0", + "postcss-modules-values": "^2.0.0", "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" + "schema-utils": "^1.0.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "minimist": "^1.2.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } @@ -2276,7 +2145,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, @@ -2297,187 +2166,43 @@ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", "dev": true }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "dev": true, - "requires": { - "ms": "^2.1.1" + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" }, "dependencies": { "ms": { @@ -2562,12 +2287,6 @@ } } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2750,9 +2469,9 @@ } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "esrecurse": { @@ -2876,29 +2595,6 @@ "is-extglob": "^1.0.0" } }, - "extract-text-webpack-plugin": { - "version": "4.0.0-beta.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", - "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", - "dev": true, - "requires": { - "async": "^2.4.1", - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, - "requires": { - "lodash": "^4.14.0" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -2995,12 +2691,6 @@ "locate-path": "^2.0.0" } }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", @@ -3143,7 +2833,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -3154,7 +2845,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3271,7 +2963,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3283,6 +2976,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3416,7 +3110,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3428,6 +3123,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3549,6 +3245,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3915,12 +3612,6 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3945,12 +3636,12 @@ "dev": true }, "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.0.0.tgz", + "integrity": "sha512-bA/xGiwWM17qjllIs9X/y0EjsB7e0AV08F3OL8UPsoNkNRibIuu8f1eKTnQ8QO1DteKKTxTUAn+IEWUToIwGOA==", "dev": true, "requires": { - "postcss": "^6.0.1" + "postcss": "^7.0.5" } }, "ieee754": { @@ -4068,12 +3759,6 @@ "repeating": "^2.0.0" } }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4117,12 +3802,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -4270,12 +3949,6 @@ "kind-of": "^3.0.2" } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4320,15 +3993,6 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -4422,13 +4086,13 @@ "dev": true }, "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "dev": true, "requires": { "argparse": "^1.0.7", - "esprima": "^2.6.0" + "esprima": "^4.0.0" } }, "jsbn": { @@ -4588,12 +4252,6 @@ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -4606,12 +4264,6 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, "lodash.mergewith": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", @@ -4624,12 +4276,6 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4715,12 +4361,6 @@ "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", @@ -4856,6 +4496,54 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "mini-css-extract-plugin": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", + "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -4884,9 +4572,9 @@ "dev": true }, "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -4895,10 +4583,22 @@ "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", - "pump": "^2.0.1", + "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "mixin-deep": { @@ -5183,18 +4883,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, "npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -5676,1924 +5364,152 @@ "dev": true }, "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" + "supports-color": "^6.1.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "dependencies": { "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "^5.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-filter-plugins": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", - "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-load-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", - "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", - "dev": true, - "requires": { - "cosmiconfig": "^4.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", - "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^6.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^0.4.0" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", - "dev": true, - "requires": { - "postcss": "^6.0.1" - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "^5.0.5" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" + "has-flag": "^3.0.0" } } } }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" } }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.4.tgz", + "integrity": "sha512-WvuSaTKXUqYJbnT7R3YrsNrHv/C5vRfr5VglS4bFOk0MYT4CLBfc/xgExA+x2RftlYgiBDvWmVs191Xv8S8gZQ==", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^7.0.6", + "postcss-value-parser": "^3.3.1" + } + }, + "postcss-modules-scope": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.0.1.tgz", + "integrity": "sha512-7+6k9c3/AuZ5c596LJx9n923A/j3nF3ormewYBF1RrIQvjvjXe1xE8V8A1KFyFwXbvnshT6FBZFX0k/F1igneg==", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^7.0.6" + } + }, + "postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, "preserve": { @@ -7693,28 +5609,12 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -7825,42 +5725,6 @@ "strip-indent": "^1.0.1" } }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -8139,12 +6003,6 @@ "semver": "^5.5.0" } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", @@ -8432,15 +6290,6 @@ "kind-of": "^3.2.0" } }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, "sortablejs": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.7.0.tgz", @@ -8551,12 +6400,12 @@ } }, "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { @@ -8660,12 +6509,6 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -8731,13 +6574,50 @@ } }, "style-loader": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", - "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5" + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "supports-color": { @@ -8749,21 +6629,6 @@ "has-flag": "^3.0.0" } }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - } - }, "tapable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", @@ -9128,30 +6993,130 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==" }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, "requires": { - "commander": "~2.13.0", + "commander": "~2.17.1", "source-map": "~0.6.1" } }, "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.1.tgz", + "integrity": "sha512-TQEcyMNkObX/H+FfcKjiDgs5RcXX8vW2UUUrDTOfQgg3lrafztfeM5WAwXo+AzqozJK6NP9w98xNpG/dutzSsg==", "dev": true, "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", + "cacache": "^11.2.0", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", "serialize-javascript": "^1.4.0", "source-map": "^0.6.1", - "uglify-es": "^3.3.4", + "uglify-js": "^3.0.0", "webpack-sources": "^1.1.0", "worker-farm": "^1.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "ultron": { @@ -9223,18 +7188,6 @@ } } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -9399,12 +7352,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "vendors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -10356,12 +8303,6 @@ "source-map": "~0.6.1" } }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index dc90689d3d8..1cbfdb3e9ba 100644 --- a/package.json +++ b/package.json @@ -13,17 +13,17 @@ "@babel/core": "^7.1.6", "@babel/polyfill": "^7.0.0", "@babel/preset-env": "^7.1.6", - "autoprefixer": "^8.6.5", + "autoprefixer": "^9.4.7", "babel-loader": "^8.0.4", - "css-loader": "^0.28.11", - "extract-text-webpack-plugin": "^4.0.0-beta.0", + "css-loader": "^2.1.0", "livereload": "^0.7.0", + "mini-css-extract-plugin": "^0.5.0", "node-sass": "^4.10.0", "npm-run-all": "^4.1.5", - "postcss-loader": "^2.1.6", + "postcss-loader": "^3.0.0", "sass-loader": "^7.1.0", - "style-loader": "^0.21.0", - "uglifyjs-webpack-plugin": "^1.3.0", + "style-loader": "^0.23.1", + "uglifyjs-webpack-plugin": "^2.1.1", "webpack": "^4.26.1", "webpack-cli": "^3.1.2" }, diff --git a/resources/assets/icons/add.svg b/resources/assets/icons/add.svg index 75e3753dc41..edd367b2d8c 100644 --- a/resources/assets/icons/add.svg +++ b/resources/assets/icons/add.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/icons/books.svg b/resources/assets/icons/books.svg new file mode 100644 index 00000000000..240201fb3db --- /dev/null +++ b/resources/assets/icons/books.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/resources/assets/icons/bookshelf.svg b/resources/assets/icons/bookshelf.svg index 03da68f9629..f1e45eaf996 100644 --- a/resources/assets/icons/bookshelf.svg +++ b/resources/assets/icons/bookshelf.svg @@ -1,2 +1 @@ - - + \ No newline at end of file diff --git a/resources/assets/icons/check.svg b/resources/assets/icons/check.svg new file mode 100644 index 00000000000..93607ef7e91 --- /dev/null +++ b/resources/assets/icons/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/chevron-right.svg b/resources/assets/icons/chevron-right.svg new file mode 100644 index 00000000000..96540b9ea05 --- /dev/null +++ b/resources/assets/icons/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/sort-down.svg b/resources/assets/icons/sort-down.svg new file mode 100644 index 00000000000..61fa6c7f779 --- /dev/null +++ b/resources/assets/icons/sort-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/sort-up.svg b/resources/assets/icons/sort-up.svg new file mode 100644 index 00000000000..985cc626fb0 --- /dev/null +++ b/resources/assets/icons/sort-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/js/components/breadcrumb-listing.js b/resources/assets/js/components/breadcrumb-listing.js new file mode 100644 index 00000000000..1e2fe9ea463 --- /dev/null +++ b/resources/assets/js/components/breadcrumb-listing.js @@ -0,0 +1,58 @@ + + +class BreadcrumbListing { + + constructor(elem) { + this.elem = elem; + this.searchInput = elem.querySelector('input'); + this.loadingElem = elem.querySelector('.loading-container'); + this.entityListElem = elem.querySelector('.breadcrumb-listing-entity-list'); + this.toggleElem = elem.querySelector('[dropdown-toggle]'); + + // this.loadingElem.style.display = 'none'; + const entityDescriptor = elem.getAttribute('breadcrumb-listing').split(':'); + this.entityType = entityDescriptor[0]; + this.entityId = Number(entityDescriptor[1]); + + this.toggleElem.addEventListener('click', this.onShow.bind(this)); + this.searchInput.addEventListener('input', this.onSearch.bind(this)); + } + + onShow() { + this.loadEntityView(); + } + + onSearch() { + const input = this.searchInput.value.toLowerCase().trim(); + const listItems = this.entityListElem.querySelectorAll('.entity-list-item'); + for (let listItem of listItems) { + const match = !input || listItem.textContent.toLowerCase().includes(input); + listItem.style.display = match ? 'flex' : 'none'; + } + } + + loadEntityView() { + this.toggleLoading(true); + + const params = { + 'entity_id': this.entityId, + 'entity_type': this.entityType, + }; + + window.$http.get('/search/entity/siblings', {params}).then(resp => { + this.entityListElem.innerHTML = resp.data; + }).catch(err => { + console.error(err); + }).then(() => { + this.toggleLoading(false); + this.onSearch(); + }); + } + + toggleLoading(show = false) { + this.loadingElem.style.display = show ? 'block' : 'none'; + } + +} + +export default BreadcrumbListing; \ No newline at end of file diff --git a/resources/assets/js/components/dropdown.js b/resources/assets/js/components/dropdown.js index dda42e868ee..400ddb57612 100644 --- a/resources/assets/js/components/dropdown.js +++ b/resources/assets/js/components/dropdown.js @@ -6,7 +6,7 @@ class DropDown { constructor(elem) { this.container = elem; - this.menu = elem.querySelector('ul'); + this.menu = elem.querySelector('ul, [dropdown-menu]'); this.toggle = elem.querySelector('[dropdown-toggle]'); this.setupListeners(); } diff --git a/resources/assets/js/components/entity-selector.js b/resources/assets/js/components/entity-selector.js index 461bf73217e..58879a20c0c 100644 --- a/resources/assets/js/components/entity-selector.js +++ b/resources/assets/js/components/entity-selector.js @@ -5,15 +5,17 @@ class EntitySelector { this.elem = elem; this.search = ''; this.lastClick = 0; + this.selectedItemData = null; - let entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter'; - let entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view'; + const entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter'; + const entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view'; this.searchUrl = window.baseUrl(`/ajax/search/entities?types=${encodeURIComponent(entityTypes)}&permission=${encodeURIComponent(entityPermission)}`); this.input = elem.querySelector('[entity-selector-input]'); this.searchInput = elem.querySelector('[entity-selector-search]'); this.loading = elem.querySelector('[entity-selector-loading]'); this.resultsContainer = elem.querySelector('[entity-selector-results]'); + this.addButton = elem.querySelector('[entity-selector-add-button]'); this.elem.addEventListener('click', this.onClick.bind(this)); @@ -26,10 +28,20 @@ class EntitySelector { this.searchEntities(this.searchInput.value); }, 200); }); + this.searchInput.addEventListener('keydown', event => { if (event.keyCode === 13) event.preventDefault(); }); + if (this.addButton) { + this.addButton.addEventListener('click', event => { + if (this.selectedItemData) { + this.confirmSelection(this.selectedItemData); + this.unselectAll(); + } + }); + } + this.showLoading(); this.initialLoad(); } @@ -53,7 +65,7 @@ class EntitySelector { searchEntities(searchTerm) { this.input.value = ''; - let url = this.searchUrl + `&term=${encodeURIComponent(searchTerm)}`; + let url = `${this.searchUrl}&term=${encodeURIComponent(searchTerm)}`; window.$http.get(url).then(resp => { this.resultsContainer.innerHTML = resp.data; this.hideLoading(); @@ -68,49 +80,54 @@ class EntitySelector { } onClick(event) { - let t = event.target; - - if (t.matches('.entity-list-item *')) { + const listItem = event.target.closest('[data-entity-type]'); + if (listItem) { event.preventDefault(); event.stopPropagation(); - let item = t.closest('[data-entity-type]'); - this.selectItem(item); - } else if (t.matches('[data-entity-type]')) { - this.selectItem(t) + this.selectItem(listItem); } - } selectItem(item) { - let isDblClick = this.isDoubleClick(); - let type = item.getAttribute('data-entity-type'); - let id = item.getAttribute('data-entity-id'); - let isSelected = !item.classList.contains('selected') || isDblClick; + const isDblClick = this.isDoubleClick(); + const type = item.getAttribute('data-entity-type'); + const id = item.getAttribute('data-entity-id'); + const isSelected = (!item.classList.contains('selected') || isDblClick); this.unselectAll(); this.input.value = isSelected ? `${type}:${id}` : ''; - if (!isSelected) window.$events.emit('entity-select-change', null); + const link = item.getAttribute('href'); + const name = item.querySelector('.entity-list-item-name').textContent; + const data = {id: Number(id), name: name, link: link}; + if (isSelected) { item.classList.add('selected'); - item.classList.add('primary-background'); + this.selectedItemData = data; + } else { + window.$events.emit('entity-select-change', null) } + if (!isDblClick && !isSelected) return; - let link = item.querySelector('.entity-list-item-link').getAttribute('href'); - let name = item.querySelector('.entity-list-item-name').textContent; - let data = {id: Number(id), name: name, link: link}; + if (isDblClick) { + this.confirmSelection(data); + } + if (isSelected) { + window.$events.emit('entity-select-change', data) + } + } - if (isDblClick) window.$events.emit('entity-select-confirm', data); - if (isSelected) window.$events.emit('entity-select-change', data); + confirmSelection(data) { + window.$events.emit('entity-select-confirm', data); } unselectAll() { let selected = this.elem.querySelectorAll('.selected'); - for (let i = 0, len = selected.length; i < len; i++) { - selected[i].classList.remove('selected'); - selected[i].classList.remove('primary-background'); + for (let selectedElem of selected) { + selectedElem.classList.remove('selected', 'primary-background'); } + this.selectedItemData = null; } } diff --git a/resources/assets/js/components/expand-toggle.js b/resources/assets/js/components/expand-toggle.js index 6f317db62bd..a6a38981838 100644 --- a/resources/assets/js/components/expand-toggle.js +++ b/resources/assets/js/components/expand-toggle.js @@ -3,8 +3,13 @@ class ExpandToggle { constructor(elem) { this.elem = elem; - this.isOpen = false; + + // Component state + this.isOpen = elem.getAttribute('expand-toggle-is-open') === 'yes'; + this.updateEndpoint = elem.getAttribute('expand-toggle-update-endpoint'); this.selector = elem.getAttribute('expand-toggle'); + + // Listener setup elem.addEventListener('click', this.click.bind(this)); } @@ -53,11 +58,20 @@ class ExpandToggle { click(event) { event.preventDefault(); - let matchingElems = document.querySelectorAll(this.selector); - for (let i = 0, len = matchingElems.length; i < len; i++) { - this.isOpen ? this.close(matchingElems[i]) : this.open(matchingElems[i]); + + const matchingElems = document.querySelectorAll(this.selector); + for (let match of matchingElems) { + this.isOpen ? this.close(match) : this.open(match); } + this.isOpen = !this.isOpen; + this.updateSystemAjax(this.isOpen); + } + + updateSystemAjax(isOpen) { + window.$http.patch(this.updateEndpoint, { + expand: isOpen ? 'true' : 'false' + }); } } diff --git a/resources/assets/js/components/header-mobile-toggle.js b/resources/assets/js/components/header-mobile-toggle.js new file mode 100644 index 00000000000..eccd4b8f0a6 --- /dev/null +++ b/resources/assets/js/components/header-mobile-toggle.js @@ -0,0 +1,31 @@ + +class HeaderMobileToggle { + + constructor(elem) { + this.elem = elem; + this.toggleButton = elem.querySelector('.mobile-menu-toggle'); + this.menu = elem.querySelector('.header-links'); + this.open = false; + + this.toggleButton.addEventListener('click', this.onToggle.bind(this)); + this.onWindowClick = this.onWindowClick.bind(this); + } + + onToggle(event) { + this.open = !this.open; + this.menu.classList.toggle('show', this.open); + if (this.open) { + window.addEventListener('click', this.onWindowClick) + } else { + window.removeEventListener('click', this.onWindowClick) + } + event.stopPropagation(); + } + + onWindowClick(event) { + this.onToggle(event); + } + +} + +module.exports = HeaderMobileToggle; \ No newline at end of file diff --git a/resources/assets/js/components/index.js b/resources/assets/js/components/index.js index bf6fbf61970..355b9647380 100644 --- a/resources/assets/js/components/index.js +++ b/resources/assets/js/components/index.js @@ -18,7 +18,11 @@ import toggleSwitch from "./toggle-switch"; import pageDisplay from "./page-display"; import shelfSort from "./shelf-sort"; import homepageControl from "./homepage-control"; - +import headerMobileToggle from "./header-mobile-toggle"; +import listSortControl from "./list-sort-control"; +import triLayout from "./tri-layout"; +import breadcrumbListing from "./breadcrumb-listing"; +import permissionsTable from "./permissions-table"; const componentMapping = { 'dropdown': dropdown, @@ -41,6 +45,11 @@ const componentMapping = { 'page-display': pageDisplay, 'shelf-sort': shelfSort, 'homepage-control': homepageControl, + 'header-mobile-toggle': headerMobileToggle, + 'list-sort-control': listSortControl, + 'tri-layout': triLayout, + 'breadcrumb-listing': breadcrumbListing, + 'permissions-table': permissionsTable, }; window.components = {}; @@ -79,4 +88,4 @@ function initAll(parentElement) { window.components.init = initAll; -export default initAll; \ No newline at end of file +export default initAll; diff --git a/resources/assets/js/components/list-sort-control.js b/resources/assets/js/components/list-sort-control.js new file mode 100644 index 00000000000..d463ed0b7df --- /dev/null +++ b/resources/assets/js/components/list-sort-control.js @@ -0,0 +1,42 @@ +/** + * ListSortControl + * Manages the logic for the control which provides list sorting options. + */ +class ListSortControl { + + constructor(elem) { + this.elem = elem; + + this.sortInput = elem.querySelector('[name="sort"]'); + this.orderInput = elem.querySelector('[name="order"]'); + this.form = elem.querySelector('form'); + + this.elem.addEventListener('click', event => { + if (event.target.closest('[data-sort-value]') !== null) { + this.sortOptionClick(event); + } + if (event.target.closest('[data-sort-dir]') !== null) { + this.sortDirectionClick(event); + } + }) + + } + + sortOptionClick(event) { + const sortOption = event.target.closest('[data-sort-value]'); + this.sortInput.value = sortOption.getAttribute('data-sort-value'); + event.preventDefault(); + this.form.submit(); + } + + sortDirectionClick(event) { + const currentDir = this.orderInput.value; + const newDir = (currentDir === 'asc') ? 'desc' : 'asc'; + this.orderInput.value = newDir; + event.preventDefault(); + this.form.submit(); + } + +} + +export default ListSortControl; \ No newline at end of file diff --git a/resources/assets/js/components/markdown-editor.js b/resources/assets/js/components/markdown-editor.js index b8e2bc040c8..96cc1e6d10d 100644 --- a/resources/assets/js/components/markdown-editor.js +++ b/resources/assets/js/components/markdown-editor.js @@ -71,6 +71,19 @@ class MarkdownEditor { if (action === 'insertDrawing') this.actionStartDrawing(); }); + // Mobile section toggling + this.elem.addEventListener('click', event => { + const toolbarLabel = event.target.closest('.editor-toolbar-label'); + if (!toolbarLabel) return; + + const currentActiveSections = this.elem.querySelectorAll('.markdown-editor-wrap'); + for (let activeElem of currentActiveSections) { + activeElem.classList.remove('active'); + } + + toolbarLabel.closest('.markdown-editor-wrap').classList.add('active'); + }); + window.$events.listen('editor-markdown-update', value => { this.cm.setValue(value); this.updateAndRender(); diff --git a/resources/assets/js/components/overlay.js b/resources/assets/js/components/overlay.js index 2dbf4eb9a87..1ba5efceadf 100644 --- a/resources/assets/js/components/overlay.js +++ b/resources/assets/js/components/overlay.js @@ -6,7 +6,7 @@ class Overlay { elem.addEventListener('click', event => { if (event.target === elem) return this.hide(); }); - let closeButtons = elem.querySelectorAll('.overlay-close'); + let closeButtons = elem.querySelectorAll('.popup-header-close'); for (let i=0; i < closeButtons.length; i++) { closeButtons[i].addEventListener('click', this.hide.bind(this)); } diff --git a/resources/assets/js/components/page-comments.js b/resources/assets/js/components/page-comments.js index c86b90d2ca4..975ff5a824b 100644 --- a/resources/assets/js/components/page-comments.js +++ b/resources/assets/js/components/page-comments.js @@ -54,7 +54,7 @@ class PageComments { commentElem.querySelector('[comment-edit-container]').style.display = 'block'; let textArea = commentElem.querySelector('[comment-edit-container] textarea'); let lineCount = textArea.value.split('\n').length; - textArea.style.height = (lineCount * 20) + 'px'; + textArea.style.height = ((lineCount * 20) + 40) + 'px'; this.editingComment = commentElem; } @@ -88,6 +88,7 @@ class PageComments { commentElem.parentNode.removeChild(commentElem); window.$events.emit('success', window.trans('entities.comment_deleted_success')); this.updateCount(); + this.hideForm(); }); } @@ -129,7 +130,7 @@ class PageComments { showForm() { this.formContainer.style.display = 'block'; this.formContainer.parentNode.style.display = 'block'; - this.elem.querySelector('[comment-add-button]').style.display = 'none'; + this.elem.querySelector('[comment-add-button-container]').style.display = 'none'; this.formInput.focus(); window.scrollToElement(this.formInput); } @@ -137,7 +138,18 @@ class PageComments { hideForm() { this.formContainer.style.display = 'none'; this.formContainer.parentNode.style.display = 'none'; - this.elem.querySelector('[comment-add-button]').style.display = 'block'; + const addButtonContainer = this.elem.querySelector('[comment-add-button-container]'); + if (this.getCommentCount() > 0) { + this.elem.appendChild(addButtonContainer) + } else { + const countBar = this.elem.querySelector('[comment-count-bar]'); + countBar.appendChild(addButtonContainer); + } + addButtonContainer.style.display = 'block'; + } + + getCommentCount() { + return this.elem.querySelectorAll('.comment-box[comment]').length; } setReply(commentElem) { diff --git a/resources/assets/js/components/page-display.js b/resources/assets/js/components/page-display.js index bca641cb616..1aeeaf248a6 100644 --- a/resources/assets/js/components/page-display.js +++ b/resources/assets/js/components/page-display.js @@ -208,8 +208,8 @@ class PageDisplay { let pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts); // observe each heading - for (let i = 0; i !== headings.length; ++i) { - pageNavObserver.observe(headings[i]); + for (let heading of headings) { + pageNavObserver.observe(heading); } } @@ -221,14 +221,9 @@ class PageDisplay { } function toggleAnchorHighlighting(elementId, shouldHighlight) { - let anchorsToHighlight = pageNav.querySelectorAll('a[href="#' + elementId + '"]'); - for (let i = 0; i < anchorsToHighlight.length; i++) { - // Change below to use classList.toggle when IE support is dropped. - if (shouldHighlight) { - anchorsToHighlight[i].classList.add('current-heading'); - } else { - anchorsToHighlight[i].classList.remove('current-heading'); - } + const anchorsToHighlight = pageNav.querySelectorAll('a[href="#' + elementId + '"]'); + for (let anchor of anchorsToHighlight) { + anchor.closest('li').classList.toggle('current-heading', shouldHighlight); } } } diff --git a/resources/assets/js/components/permissions-table.js b/resources/assets/js/components/permissions-table.js new file mode 100644 index 00000000000..baad7525833 --- /dev/null +++ b/resources/assets/js/components/permissions-table.js @@ -0,0 +1,66 @@ + +class PermissionsTable { + + constructor(elem) { + this.container = elem; + + // Handle toggle all event + const toggleAll = elem.querySelector('[permissions-table-toggle-all]'); + toggleAll.addEventListener('click', this.toggleAllClick.bind(this)); + + // Handle toggle row event + const toggleRowElems = elem.querySelectorAll('[permissions-table-toggle-all-in-row]'); + for (let toggleRowElem of toggleRowElems) { + toggleRowElem.addEventListener('click', this.toggleRowClick.bind(this)); + } + + // Handle toggle column event + const toggleColumnElems = elem.querySelectorAll('[permissions-table-toggle-all-in-column]'); + for (let toggleColElem of toggleColumnElems) { + toggleColElem.addEventListener('click', this.toggleColumnClick.bind(this)); + } + } + + toggleAllClick(event) { + event.preventDefault(); + this.toggleAllInElement(this.container); + } + + toggleRowClick(event) { + event.preventDefault(); + this.toggleAllInElement(event.target.closest('tr')); + } + + toggleColumnClick(event) { + event.preventDefault(); + + const tableCell = event.target.closest('th,td'); + const colIndex = Array.from(tableCell.parentElement.children).indexOf(tableCell); + const tableRows = tableCell.closest('table').querySelectorAll('tr'); + const inputsToToggle = []; + + for (let row of tableRows) { + const targetCell = row.children[colIndex]; + if (targetCell) { + inputsToToggle.push(...targetCell.querySelectorAll('input[type=checkbox]')); + } + } + this.toggleAllInputs(inputsToToggle); + } + + toggleAllInElement(domElem) { + const inputsToToggle = domElem.querySelectorAll('input[type=checkbox]'); + this.toggleAllInputs(inputsToToggle); + } + + toggleAllInputs(inputsToToggle) { + const currentState = inputsToToggle.length > 0 ? inputsToToggle[0].checked : false; + for (let checkbox of inputsToToggle) { + checkbox.checked = !currentState; + checkbox.dispatchEvent(new Event('change')); + } + } + +} + +export default PermissionsTable; \ No newline at end of file diff --git a/resources/assets/js/components/toggle-switch.js b/resources/assets/js/components/toggle-switch.js index 957a4164214..3be67d5dc94 100644 --- a/resources/assets/js/components/toggle-switch.js +++ b/resources/assets/js/components/toggle-switch.js @@ -3,15 +3,15 @@ class ToggleSwitch { constructor(elem) { this.elem = elem; - this.input = elem.querySelector('input'); + this.input = elem.querySelector('input[type=hidden]'); + this.checkbox = elem.querySelector('input[type=checkbox]'); - this.elem.onclick = this.onClick.bind(this); + this.checkbox.addEventListener('change', this.onClick.bind(this)); } onClick(event) { - let checked = this.input.value !== 'true'; + let checked = this.checkbox.checked; this.input.value = checked ? 'true' : 'false'; - checked ? this.elem.classList.add('active') : this.elem.classList.remove('active'); } } diff --git a/resources/assets/js/components/tri-layout.js b/resources/assets/js/components/tri-layout.js new file mode 100644 index 00000000000..0ae7df976b3 --- /dev/null +++ b/resources/assets/js/components/tri-layout.js @@ -0,0 +1,95 @@ + +class TriLayout { + + constructor(elem) { + this.elem = elem; + + this.lastLayoutType = 'none'; + this.onDestroy = null; + this.scrollCache = { + 'content': 0, + 'info': 0, + }; + this.lastTabShown = 'content'; + + // Bind any listeners + this.mobileTabClick = this.mobileTabClick.bind(this); + + // Watch layout changes + this.updateLayout(); + window.addEventListener('resize', event => { + this.updateLayout(); + }, {passive: true}); + } + + updateLayout() { + let newLayout = 'tablet'; + if (window.innerWidth <= 1000) newLayout = 'mobile'; + if (window.innerWidth >= 1400) newLayout = 'desktop'; + if (newLayout === this.lastLayoutType) return; + + if (this.onDestroy) { + this.onDestroy(); + this.onDestroy = null; + } + + if (newLayout === 'desktop') { + this.setupDesktop(); + } else if (newLayout === 'mobile') { + this.setupMobile(); + } + + this.lastLayoutType = newLayout; + } + + setupMobile() { + const layoutTabs = document.querySelectorAll('[tri-layout-mobile-tab]'); + for (let tab of layoutTabs) { + tab.addEventListener('click', this.mobileTabClick); + } + + this.onDestroy = () => { + for (let tab of layoutTabs) { + tab.removeEventListener('click', this.mobileTabClick); + } + } + } + + setupDesktop() { + // + } + + + /** + * Action to run when the mobile info toggle bar is clicked/tapped + * @param event + */ + mobileTabClick(event) { + const tab = event.target.getAttribute('tri-layout-mobile-tab'); + this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop; + + // Set tab status + const activeTabs = document.querySelectorAll('.tri-layout-mobile-tab.active'); + for (let tab of activeTabs) { + tab.classList.remove('active'); + } + event.target.classList.add('active'); + + // Toggle section + const showInfo = (tab === 'info'); + this.elem.classList.toggle('show-info', showInfo); + + // Set the scroll position from cache + const pageHeader = document.querySelector('header'); + const defaultScrollTop = pageHeader.getBoundingClientRect().bottom; + document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop; + setTimeout(() => { + document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop; + }, 50); + + this.lastTabShown = tab; + } + +} + +export default TriLayout; \ No newline at end of file diff --git a/resources/assets/js/components/wysiwyg-editor.js b/resources/assets/js/components/wysiwyg-editor.js index 9deb1d0a7a0..ce5cfbf4e66 100644 --- a/resources/assets/js/components/wysiwyg-editor.js +++ b/resources/assets/js/components/wysiwyg-editor.js @@ -432,7 +432,7 @@ class WysiwygEditor { plugins: this.plugins, imagetools_toolbar: 'imageoptions', toolbar: this.getToolBar(), - content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}", + content_style: "html, body {background: #FFF;} body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}", style_formats: [ {title: "Header Large", format: "h2"}, {title: "Header Medium", format: "h3"}, @@ -517,6 +517,16 @@ class WysiwygEditor { if (scrollId) { scrollToText(scrollId); } + + // Override for touch events to allow scroll on mobile + const container = editor.getContainer(); + const toolbarButtons = container.querySelectorAll('.mce-btn'); + for (let button of toolbarButtons) { + button.addEventListener('touchstart', event => { + event.stopPropagation(); + }); + } + window.editor = editor; }); function editorChange() { @@ -600,6 +610,7 @@ class WysiwygEditor { // Paste image-uploads editor.on('paste', event => editorPaste(event, editor, context)); + } }; } diff --git a/resources/assets/sass/_animations.scss b/resources/assets/sass/_animations.scss index c03553d15bf..85fd9620639 100644 --- a/resources/assets/sass/_animations.scss +++ b/resources/assets/sass/_animations.scss @@ -36,26 +36,6 @@ } } -.anim.menuIn { - transform-origin: 100% 0%; - animation-name: menuIn; - animation-duration: 120ms; - animation-delay: 0s; - animation-timing-function: cubic-bezier(.62, .28, .23, .99); -} - -@keyframes menuIn { - from { - opacity: 0; - transform: scale3d(0, 0, 1); - } - - to { - opacity: 1; - transform: scale3d(1, 1, 1); - } -} - @keyframes loadingBob { 0% { transform: translate3d(0, 0, 0); @@ -89,8 +69,4 @@ animation-duration: 180ms; animation-delay: 0s; animation-timing-function: cubic-bezier(.62, .28, .23, .99); -} - -.selectFade { - transition: background-color ease-in-out 3000ms; } \ No newline at end of file diff --git a/resources/assets/sass/_blocks.scss b/resources/assets/sass/_blocks.scss index c0f02ed7d78..efdefc016fb 100644 --- a/resources/assets/sass/_blocks.scss +++ b/resources/assets/sass/_blocks.scss @@ -1,136 +1,7 @@ -/* -* This file container all block styling including background shading, -* margins, paddings & borders. -*/ - - -/* -* Background Shading -*/ -.shaded { - background-color: #f1f1f1; - &.pos { - background-color: lighten($positive, 40%); - } - &.neg { - background-color: lighten($negative, 20%); - } - &.primary { - background-color: lighten($primary, 40%); - } - &.secondary { - background-color: lighten($secondary, 30%); - } -} - -/* -* Bordering -*/ -.bordered { - border: 1px solid #BBB; - &.pos { - border-color: $positive; - } - &.neg { - border-color: $negative; - } - &.primary { - border-color: $primary; - } - &.secondary { - border-color: $secondary; - } - &.thick { - border-width: 2px; - } -} -.rounded { - border-radius: 3px; -} - -/* -* Padding -*/ -.nopadding { - padding: 0; -} -.padded { - padding: $-l; - &.large { - padding: $-xl; - } - >h1, >h2, >h3, >h4 { - &:first-child { - margin-top: 0.1em; - } - } -} -.padded-vertical, .padded-top { - padding-top: $-m; - &.large { - padding-top: $-xl; - } -} - -.padded-vertical, .padded-bottom { - padding-bottom: $-m; - &.large { - padding-bottom: $-xl; - } -} -.padded-horizontal, .padded-left { - padding-left: $-m; - &.large { - padding-left: $-xl; - } -} -.padded-horizontal, .padded-right { - padding-right: $-m; - &.large { - padding-right: $-xl; - } -} - -/* -* Margins -*/ -.margins { - margin: $-l; - &.large { - margin: $-xl; - } -} -.margins-vertical, .margin-top { - margin-top: $-m; - &.large { - margin-top: $-xl; - } -} -.margins-vertical, .margin-bottom { - margin-bottom: $-m; - &.large { - margin-bottom: $-xl; - } -} -.margins-horizontal, .margin-left { - margin-left: $-m; - &.large { - margin-left: $-xl; - } -} -.margins-horizontal, .margin-right { - margin-right: $-m; - &.large { - margin-right: $-xl; - } -} - - /** * Callouts */ - .callout { border-left: 3px solid #BBB; background-color: #EEE; @@ -182,19 +53,22 @@ } } +/** + * Card-style blocks + */ + .card { - margin: $-m; background-color: #FFF; - box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.2); + box-shadow: $bs-card; + border-radius: 3px; + border: 1px solid transparent; h3 { - padding: $-m; - border-bottom: 1px solid #E8E8E8; + padding: $-m $-m $-xs; margin: 0; - font-size: $fs-s; - color: #888; - fill: #888; + font-size: $fs-m; + color: #222; + fill: #222; font-weight: 400; - text-transform: uppercase; } h3 a { line-height: 1; @@ -208,18 +82,11 @@ } } -.sidebar .card { - h3, .body, .empty-text { - padding: $-s $-m; - } -} - .card.drag-card { border: 1px solid #DDD; border-radius: 4px; display: flex; - padding: 0; - padding-left: $-s + 28px; + padding: 0 0 0 ($-s + 28px); margin: $-s 0; position: relative; .drag-card-action { @@ -227,14 +94,12 @@ } .handle, .drag-card-action { display: flex; - padding: 0; align-items: center; text-align: center; justify-content: center; width: 28px; flex-grow: 0; - padding-left: $-xs; - padding-right: $-xs; + padding: 0 $-xs; &:hover { background-color: #EEE; } @@ -246,9 +111,6 @@ margin: $-s 0; width: 100%; } - > div.padded { - padding: $-s 0 !important; - } .handle { background-color: #EEE; left: 0; @@ -263,12 +125,89 @@ } } -.well { - background-color: #F8F8F8; - padding: $-m; - border: 1px solid #DDD; +.grid-card { + display: flex; + flex-direction: column; + border: 1px solid #ddd; + margin-bottom: $-l; + border-radius: 4px; + overflow: hidden; + min-width: 100px; + color: $text-dark; + transition: border-color ease-in-out 120ms, box-shadow ease-in-out 120ms; + &:hover { + color: $text-dark; + text-decoration: none; + box-shadow: $bs-card; + } + h2 { + width: 100%; + font-size: 1.5em; + margin: 0 0 10px; + } + p { + font-size: .7rem; + margin: 0; + line-height: 1.6em; + } + .grid-card-content { + flex: 1; + border-top: 0; + border-bottom-width: 2px; + } + .grid-card-content, .grid-card-footer { + padding: $-l; + } + .grid-card-content + .grid-card-footer { + padding-top: 0; + } +} + +.bookshelf-grid-item .grid-card-content h2 a { + color: $color-bookshelf; + fill: $color-bookshelf; } +.book-grid-item .grid-card-footer { + p.small { + font-size: .8em; + margin: 0; + } +} + +.content-wrap.card { + padding: $-m $-xxl; + margin-left: auto; + margin-right: auto; + margin-bottom: $-xl; + overflow: auto; + min-height: 60vh; + &.auto-height { + min-height: 0; + } + &.fill-width { + width: 100%; + } +} +@include smaller-than($xxl) { + .content-wrap.card { + padding: $-l $-xl; + } +} +@include smaller-than($m) { + .content-wrap.card { + padding: $-m $-l; + } +} +@include smaller-than($s) { + .content-wrap.card { + padding: $-m $-s; + } +} + +/** + * Tags + */ .tag-item { display: inline-flex; margin-bottom: $-xs; diff --git a/resources/assets/sass/_buttons.scss b/resources/assets/sass/_buttons.scss index 2c20c3f41a5..eb7a09342ad 100644 --- a/resources/assets/sass/_buttons.scss +++ b/resources/assets/sass/_buttons.scss @@ -1,15 +1,14 @@ +button { + font-size: 100%; +} @mixin generate-button-colors($textColor, $backgroundColor) { background-color: $backgroundColor; color: $textColor; fill: $textColor; - text-transform: uppercase; border: 1px solid $backgroundColor; - vertical-align: top; &:hover { background-color: lighten($backgroundColor, 8%); - //box-shadow: $bs-med; - text-decoration: none; color: $textColor; } &:active { @@ -18,7 +17,6 @@ &:focus { background-color: lighten($backgroundColor, 4%); box-shadow: $bs-light; - text-decoration: none; color: $textColor; } } @@ -26,42 +24,36 @@ // Button Specific Variables $button-border-radius: 2px; -.button-base { +.button { text-decoration: none; - font-size: $fs-m; + font-size: 0.85rem; line-height: 1.4em; padding: $-xs*1.3 $-m; - margin: $-xs $-xs $-xs 0; + margin-top: $-xs; + margin-bottom: $-xs; display: inline-block; - border: none; font-weight: 400; outline: 0; border-radius: $button-border-radius; cursor: pointer; - transition: all ease-in-out 120ms; - box-shadow: 0; - @include generate-button-colors(#EEE, $primary); -} - -.button, input[type="button"], input[type="submit"] { - @extend .button-base; - &.pos { - @include generate-button-colors(#EEE, $positive); - } - &.neg { - @include generate-button-colors(#EEE, $negative); - } - &.secondary { - @include generate-button-colors(#EEE, $secondary); - } - &.muted { - @include generate-button-colors(#EEE, #AAA); + transition: background-color ease-in-out 120ms, box-shadow ease-in-out 120ms; + box-shadow: none; + background-color: $primary; + color: #FFF; + fill: #FFF; + text-transform: uppercase; + border: 1px solid $primary; + vertical-align: top; + &:hover, &:focus { + text-decoration: none; } - &.muted-light { - @include generate-button-colors(#666, #e4e4e4); + &:active { + background-color: darken($primary, 8%); } } - +.button.primary { + @include generate-button-colors(#FFFFFF, $primary); +} .button.outline { background-color: transparent; color: #888; @@ -71,78 +63,38 @@ $button-border-radius: 2px; box-shadow: none; background-color: #EEE; } - &.page { - border-color: $color-page; - color: $color-page; - fill: $color-page; - &:hover, &:focus, &:active { - background-color: $color-page; - color: #FFF; - fill: #FFF; - } - } - &.chapter { - border-color: $color-chapter; - color: $color-chapter; - fill: $color-chapter; - &:hover, &:focus, &:active { - background-color: $color-chapter; - color: #FFF; - fill: #FFF; - } - } - &.book { - border-color: $color-book; - color: $color-book; - fill: $color-book; - &:hover, &:focus, &:active { - background-color: $color-book; - color: #FFF; - fill: #FFF; - } - } +} + +.button + .button { + margin-left: $-s; +} + +.button.small { + font-size: 0.75rem; + padding: $-xs*1.2 $-s; } .text-button { - @extend .link; + cursor: pointer; background-color: transparent; padding: 0; margin: 0; border: none; user-select: none; + font-size: 0.75rem; + line-height: 1.4em; &:focus, &:active { outline: 0; } &:hover { text-decoration: none; } - &.neg { - color: $negative; - } -} - -.button-group { - @include clearfix; - .button, button[type="button"] { - margin: $-xs 0 $-xs 0; - float: left; - border-radius: 0; - &:first-child { - border-radius: $button-border-radius 0 0 $button-border-radius; - } - &:last-child { - border-radius: 0 $button-border-radius $button-border-radius 0; - } - } } .button.block { width: 100%; - text-align: center; + text-align: left; display: block; - &.text-left { - text-align: left; - } } .button.icon { @@ -160,9 +112,7 @@ $button-border-radius: 2px; width: 24px; height: 24px; } - padding: $-s $-m; - padding-bottom: $-s - 2px; - padding-left: $-m*2 + 24px; + padding: $-s $-m ($-s - 2px) ($-m*2 + 24px); } .button[disabled] { diff --git a/resources/assets/sass/_colors.scss b/resources/assets/sass/_colors.scss new file mode 100644 index 00000000000..4dfc9d4c3d9 --- /dev/null +++ b/resources/assets/sass/_colors.scss @@ -0,0 +1,72 @@ + +/* + * Status text colors + */ +.text-pos, .text-pos:hover, .text-pos-hover:hover { + color: $positive !important; + fill: $positive !important; +} + +.text-warn, .text-warn:hover, .text-warn-hover:hover { + color: $warning !important; + fill: $warning !important; +} + +.text-neg, .text-neg:hover, .text-neg-hover:hover { + color: $negative !important; + fill: $negative !important; +} + +/* + * Style text colors + */ +.text-primary, .text-primary:hover, .text-primary-hover:hover { + color: $primary !important; + fill: $primary !important; +} + +.text-muted { + color: lighten($text-dark, 26%) !important; + fill: lighten($text-dark, 26%) !important; + &.small, .small { + color: lighten($text-dark, 32%) !important; + fill: lighten($text-dark, 32%) !important; + } +} + +/* + * Entity text colors + */ +.text-bookshelf, .text-bookshelf:hover { + color: $color-bookshelf; + fill: $color-bookshelf; +} +.text-book, .text-book:hover { + color: $color-book; + fill: $color-book; +} +.text-page, .text-page:hover { + color: $color-page; + fill: $color-page; +} +.text-page.draft, .text-page.draft:hover { + color: $color-page-draft; + fill: $color-page-draft; +} +.text-chapter, .text-chapter:hover { + color: $color-chapter; + fill: $color-chapter; +} + +/* + * Entity background colors + */ +.bg-book { + background-color: $color-book; +} +.bg-chapter { + background-color: $color-chapter; +} +.bg-shelf { + background-color: $color-bookshelf; +} \ No newline at end of file diff --git a/resources/assets/sass/_components.scss b/resources/assets/sass/_components.scss index 1f34166c61f..33bc5e71de3 100644 --- a/resources/assets/sass/_components.scss +++ b/resources/assets/sass/_components.scss @@ -54,13 +54,18 @@ transition: all ease-in-out 180ms; user-select: none; svg[data-icon="caret-right"] { + margin-right: 0; + font-size: 1rem; transition: all ease-in-out 180ms; transform: rotate(0deg); - transform-origin: 25% 50%; + transform-origin: 50% 50%; } &.open svg[data-icon="caret-right"] { transform: rotate(90deg); } + svg[data-icon="caret-right"] + * { + margin-left: $-xs; + } } [overlay] { @@ -110,7 +115,7 @@ } } -.corner-button { +.popup-footer button, .popup-header-close { position: absolute; top: 0; right: 0; @@ -118,6 +123,16 @@ height: 40px; border-radius: 0; box-shadow: none; + &:active { + outline: 0; + } +} +.popup-header-close { + background-color: transparent; + border: 0; + color: #FFF; + font-size: 16px; + padding: 0 $-m; } .popup-header, .popup-footer { @@ -130,6 +145,9 @@ padding: 8px $-m; } } +.popup-footer { + margin-top: 1px; +} body.flexbox-support #entity-selector-wrap .popup-body .form-group { height: 444px; min-height: 444px; @@ -137,6 +155,9 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { #entity-selector-wrap .popup-body .form-group { margin: 0; } +.popup-body .entity-selector-container { + flex: 1; +} .image-manager-body { min-height: 70vh; @@ -583,27 +604,26 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { } .comment-box { - clear: left; border: 1px solid #DDD; - margin-bottom: $-s; - border-radius: 3px; + border-radius: 4px; + background-color: #FFF; .content { - padding: $-s; font-size: 0.666em; p, ul, ol { font-size: $fs-m; margin: .5em 0; } } - .reply-row { - padding: $-xs $-s; + .actions { + opacity: 0; + transition: opacity ease-in-out 120ms; + } + &:hover .actions { + opacity: 1; } } .comment-box .header { - padding: $-xs $-s; - background-color: #f8f8f8; - border-bottom: 1px solid #DDD; .meta { img, a, span { display: inline-block; @@ -626,4 +646,11 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { #tag-manager .drag-card { max-width: 500px; +} + +.permissions-table [permissions-table-toggle-all-in-row] { + display: none; +} +.permissions-table tr:hover [permissions-table-toggle-all-in-row] { + display: inline; } \ No newline at end of file diff --git a/resources/assets/sass/_forms.scss b/resources/assets/sass/_forms.scss index 6b3ed381549..f40c92a194d 100644 --- a/resources/assets/sass/_forms.scss +++ b/resources/assets/sass/_forms.scss @@ -63,6 +63,34 @@ } } +@include smaller-than($m) { + #markdown-editor { + flex-direction: column; + } + #markdown-editor .markdown-editor-wrap { + width: 100%; + max-width: 100%; + } + #markdown-editor .editor-toolbar { + padding: 0; + } + #markdown-editor .editor-toolbar > * { + padding: $-xs $-s; + } + .editor-toolbar-label { + float: none !important; + border-bottom: 1px solid #DDD; + display: block; + } + .markdown-editor-wrap:not(.active) .editor-toolbar + div, .markdown-editor-wrap:not(.active) .editor-toolbar .buttons { + display: none; + } + #markdown-editor .markdown-editor-wrap:not(.active) { + flex-grow: 0; + flex: none; + } +} + .markdown-display { padding: 0 $-m 0; margin-left: -1px; @@ -98,7 +126,7 @@ label { line-height: 1.4em; font-size: 0.94em; font-weight: 400; - color: #999; + color: #666; padding-bottom: 2px; margin-bottom: 0.2em; &.inline { @@ -139,56 +167,77 @@ input[type=date] { } .toggle-switch { - display: inline-block; - background-color: #BBB; - width: 36px; - height: 14px; - border-radius: 7px; - position: relative; - transition: all ease-in-out 120ms; - cursor: pointer; user-select: none; - &:after { - content: ''; - display: block; - position: relative; - left: 0; - margin-top: -3px; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: #fafafa; - border: 1px solid #CCC; - box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); - transition: all ease-in-out 120ms; - } - &.active { - background-color: rgba($positive, 0.4); - &:after { - left: 16px; - background-color: $positive; - border: darken($positive, 20%); + display: inline-grid; + grid-template-columns: (16px + $-s) 1fr; + align-items: center; + margin: $-m 0; + .custom-checkbox { + width: 16px; + height: 16px; + border-radius: 2px; + display: inline-block; + border: 2px solid currentColor; + opacity: 0.6; + overflow: hidden; + fill: currentColor; + .svg-icon { + width: 100%; + height: 100%; + margin: 0; + bottom: auto; + top: -1.5px; + left: 0; + transition: transform ease-in-out 120ms; + transform: scale(0); + transform-origin: center center; } } + input[type=checkbox] { + display: none; + } + input[type=checkbox]:checked + .custom-checkbox .svg-icon { + transform: scale(1); + } + .custom-checkbox:hover { + background-color: rgba(0, 0, 0, 0.05); + opacity: 0.8; + } } -.toggle-switch-checkbox { - display: none; -} -input:checked + .toggle-switch { - background-color: rgba($positive, 0.4); - &:after { - left: 16px; - background-color: $positive; - border: darken($positive, 20%); +.toggle-switch-list { + .toggle-switch { + margin: $-xs 0; + } + &.compact .toggle-switch { + margin: 1px 0; } } .form-group { margin-bottom: $-s; - textarea { - display: block; +} + +.setting-list > div { + border-bottom: 1px solid #DDD; + padding: $-xl 0; + &:last-child { + border-bottom: none; + } +} +.setting-list-label { + color: #222; + font-size: 1rem; +} +.setting-list-label + p.small { + margin-bottom: 0; +} +.setting-list-label + .grid { + margin-top: $-m; +} + +.setting-list .grid, .stretch-inputs { + input[type=text], input[type=email], input[type=password], select { width: 100%; - min-height: 64px; } } @@ -197,6 +246,8 @@ input:checked + .toggle-switch { font-family: monospace; font-size: 12px; min-height: 100px; + display: block; + width: 100%; } .form-group { @@ -206,11 +257,9 @@ input:checked + .toggle-switch { } .form-group[collapsible] { - margin-left: -$-m; - margin-right: -$-m; padding: 0 $-m; - border-top: 1px solid #DDD; - border-bottom: 1px solid #DDD; + border: 1px solid #DDD; + border-radius: 4px; .collapse-title { margin-left: -$-m; margin-right: -$-m; @@ -238,9 +287,6 @@ input:checked + .toggle-switch { &.open .collapse-title label:before { transform: rotate(90deg); } - &+.form-group[collapsible] { - margin-top: -($-s + 1); - } } .inline-input-style { @@ -304,6 +350,13 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { width: 300px; max-width: 100%; } + &.flexible input { + width: 100%; + } + .search-box-cancel { + left: auto; + right: 0; + } } .outline > input { @@ -317,13 +370,6 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { } } -#login-form label[for="remember"] { - margin: 0; -} -#login-form label.toggle-switch { - margin-left: $-xl; -} - .image-picker img { background-color: #BBB; } diff --git a/resources/assets/sass/_grid.scss b/resources/assets/sass/_grid.scss deleted file mode 100644 index 0e1f85ce62c..00000000000 --- a/resources/assets/sass/_grid.scss +++ /dev/null @@ -1,930 +0,0 @@ - -/** Flexbox styling rules **/ -body.flexbox { - display: flex; - flex-direction: column; - align-items: stretch; - height: 100%; - min-height: 100%; - max-height: 100%; - overflow: hidden; - #content { - flex: 1; - display: flex; - min-height: 0; - } -} - -.flex-fill { - display: flex; - align-items: stretch; - min-height: 0; - max-width: 100%; - position: relative; - &.rows { - flex-direction: row; - } - &.columns { - flex-direction: column; - } -} - -.flex { - min-height: 0; - flex: 1; -} - -.flex.scroll { - //overflow-y: auto; - display: flex; - &.sidebar { - margin-right: -14px; - } -} -.flex.scroll .scroll-body { - overflow-y: scroll; - flex: 1; -} - -.flex-child > div { - flex: 1; -} - -.flex.sidebar { - flex: 1; - background-color: #F2F2F2; - max-width: 360px; - min-height: 90vh; - section { - margin: $-m; - } -} -.flex.sidebar + .flex.content { - flex: 3; - background-color: #FFFFFF; - padding: 0 $-l; - border-left: 1px solid #DDD; - max-width: 100%; -} -.flex.sidebar .sidebar-toggle { - display: none; -} - -@include smaller-than($xl) { - body.sidebar-layout { - padding-left: 30px; - } - .flex.sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 100; - padding-right: 30px; - width: 360px; - box-shadow: none; - transform: translate3d(-330px, 0, 0); - transition: transform ease-in-out 120ms; - display: flex; - flex-direction: column; - } - .flex.sidebar.open { - box-shadow: 1px 2px 2px 1px rgba(0,0,0,.10); - transform: translate3d(0, 0, 0); - .sidebar-toggle i { - transform: rotate(180deg); - } - } - .flex.sidebar .sidebar-toggle { - display: block; - position: absolute; - opacity: 0.9; - right: 0; - top: 0; - bottom: 0; - width: 30px; - fill: #666; - font-size: 20px; - vertical-align: middle; - text-align: center; - border: 1px solid #DDD; - border-top: 1px solid #BBB; - padding-top: $-m; - cursor: pointer; - svg { - opacity: 0.5; - transition: all ease-in-out 120ms; - margin: 0; - } - &:hover i { - opacity: 1; - } - } - .sidebar .scroll-body { - flex: 1; - overflow-y: scroll; - } - #sidebar .scroll-body.fixed { - width: auto !important; - } -} - -@include larger-than($xl) { - #sidebar .scroll-body.fixed { - z-index: 5; - position: fixed; - top: 0; - padding-right: $-m; - width: 30%; - left: 0; - height: 100%; - overflow-y: auto; - -ms-overflow-style: none; - //background-color: $primary-faded; - border-left: 1px solid #DDD; - &::-webkit-scrollbar { width: 0 !important } - } -} - - -/** Rules for all columns */ -div[class^="col-"] img { - max-width: 100%; -} - -.container { - max-width: $max-width; - margin-left: auto; - margin-right: auto; - padding-left: $-m; - padding-right: $-m; - &.fluid { - max-width: 100%; - } - &.medium { - max-width: 992px; - } - &.small { - max-width: 840px; - } - &.nopad { - padding-left: 0; - padding-right: 0; - } -} - -.row { - margin-left: -$-m; - margin-right: -$-m; -} - -.grid { - display: grid; - grid-column-gap: $-l; - grid-row-gap: $-l; - &.third { - grid-template-columns: 1fr 1fr 1fr; - } -} - -.grid-card { - display: flex; - flex-direction: column; - border: 1px solid #ddd; - min-width: 100px; - h2 { - width: 100%; - font-size: 1.5em; - margin: 0 0 10px; - } - h2 a { - display: block; - width: 100%; - line-height: 1.2; - text-decoration: none; - } - p { - font-size: .85em; - margin: 0; - line-height: 1.6em; - } - .grid-card-content { - flex: 1; - border-top: 0; - border-bottom-width: 2px; - } - .grid-card-content, .grid-card-footer { - padding: $-l; - } - .grid-card-content + .grid-card-footer { - padding-top: 0; - } -} - -.book-grid-item .grid-card-content h2 a { - color: $color-book; - fill: $color-book; -} - -.bookshelf-grid-item .grid-card-content h2 a { - color: $color-bookshelf; - fill: $color-bookshelf; -} - -.book-grid-item .grid-card-footer { - p.small { - font-size: .8em; - margin: 0; - } -} - -@include smaller-than($m) { - .grid.third { - grid-template-columns: 1fr 1fr; - } -} - -@include smaller-than($s) { - .grid.third { - grid-template-columns: 1fr; - } -} - -.float { - float: left; - &.right { - float: right; - } -} - -.block { - display: block; - position: relative; -} - -.inline { - display: inline; -} - -.block.inline { - display: inline-block; -} - -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-left: $-m; - padding-right: $-m; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0%; -} -@media (min-width: $screen-sm) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0%; - } -} -@media (min-width: $screen-md) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0%; - } -} -@media (min-width: $screen-lg) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0%; - } -} -.clearfix:before, -.clearfix:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after { - content: " "; - display: table; -} -.clearfix:after, -.container:after, -.container-fluid:after, -.row:after { - clear: both; -} -.center-block { - display: block; - margin-left: auto; - margin-right: auto; -} diff --git a/resources/assets/sass/_header.scss b/resources/assets/sass/_header.scss index b66bab394d5..7fd6d7ae94f 100644 --- a/resources/assets/sass/_header.scss +++ b/resources/assets/sass/_header.scss @@ -2,21 +2,31 @@ * Includes the main navigation header and the faded toolbar. */ +header .grid { + grid-template-columns: auto min-content auto; +} + +@include smaller-than($l) { + header .grid { + grid-template-columns: 1fr; + grid-row-gap: 0; + } +} + header { + position: relative; display: block; - z-index: 2; + z-index: 6; top: 0; background-color: $primary-dark; color: #fff; fill: #fff; - .padded { - padding: $-m; - } border-bottom: 1px solid #DDD; + box-shadow: $bs-card; + padding: $-xxs 0; .links { display: inline-block; vertical-align: top; - margin-left: $-m; } .links a { display: inline-block; @@ -28,15 +38,6 @@ header { padding-left: $-m; padding-right: 0; } - @include smaller-than($screen-md) { - .links a { - padding-left: $-s; - padding-right: $-s; - } - .dropdown-container { - padding-left: $-s; - } - } .avatar, .user-name { display: inline-block; } @@ -63,27 +64,17 @@ header { padding-top: 4px; font-size: 18px; } - @include smaller-than($screen-md) { + @include between($l, $xl) { padding-left: $-xs; .name { display: none; } } } - @include smaller-than($screen-sm) { - text-align: center; - .float.right { - float: none; - } - .links a { - padding: $-s; - } - .user-name { - padding-top: $-s; - } - } } + + .header-search { display: inline-block; } @@ -92,13 +83,16 @@ header .search-box { margin-top: 10px; input { background-color: rgba(0, 0, 0, 0.2); - border: 1px solid rgba(255, 255, 255, 0.3); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 40px; color: #EEE; z-index: 2; + padding-left: 40px; } button { fill: #EEE; z-index: 1; + left: 16px; svg { margin-right: 0; } @@ -115,20 +109,11 @@ header .search-box { :-moz-placeholder { /* Firefox 18- */ color: #DDD; } - @include smaller-than($screen-lg) { - max-width: 250px; - } - @include smaller-than($l) { + @include between($l, $xl) { max-width: 200px; } } -@include smaller-than($s) { - .header-search { - display: block; - } -} - .logo { display: inline-block; &:hover { @@ -151,10 +136,184 @@ header .search-box { height: 43px; } -.breadcrumbs span.sep { - color: #aaa; +.mobile-menu-toggle { + color: #FFF; + fill: #FFF; + font-size: 2em; + border: 2px solid rgba(255, 255, 255, 0.8); + border-radius: 4px; padding: 0 $-xs; + position: absolute; + right: $-m; + top: 13px; + line-height: 1; + cursor: pointer; + user-select: none; + svg { + margin: 0; + bottom: -2px; + } } + +@include smaller-than($l) { + header .header-links { + display: none; + background-color: #FFF; + z-index: 10; + right: $-m; + border-radius: 4px; + overflow: hidden; + position: absolute; + box-shadow: $bs-hover; + margin-top: -$-xs; + &.show { + display: block; + } + } + header .links a, header .dropdown-container ul li a { + text-align: left; + display: block; + padding: $-s $-m; + color: $text-dark; + fill: $text-dark; + svg { + margin-right: $-s; + } + &:hover { + background-color: #EEE; + color: #444; + fill: #444; + text-decoration: none; + } + } + header .dropdown-container { + display: block; + padding-left: 0; + } + header .links { + display: block; + } + header .dropdown-container ul { + display: block !important; + position: relative; + background-color: transparent; + border: 0; + padding: 0; + margin: 0; + box-shadow: none; + } +} + +.tri-layout-mobile-tabs { + position: sticky; + top: 0; + z-index: 5; + background-color: #FFF; + border-bottom: 1px solid #DDD; + box-shadow: $bs-card; +} +.tri-layout-mobile-tab { + text-align: center; + border-bottom: 3px solid #BBB; + &:first-child { + border-right: 1px solid #DDD; + } + &.active { + border-bottom-color: currentColor; + } +} + +.breadcrumbs { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; + opacity: 0.7; + .icon-list-item { + width: auto; + padding-top: $-xs; + padding-bottom: $-xs; + } + .separator { + display: inline-block; + fill: #aaa; + font-size: 1.6em; + line-height: 0.8; + margin: -2px 0 0; + } + &:hover { + opacity: 1; + } +} + +@include smaller-than($l) { + .breadcrumbs .icon-list-item { + padding: $-xs; + > span + span { + display: none; + } + > span:first-child { + margin-right: 0; + } + } +} + +.breadcrumb-listing { + position: relative; + .breadcrumb-listing-toggle { + padding: 6px; + border: 1px solid transparent; + border-radius: 4px; + &:hover { + border-color: #DDD; + } + } + .svg-icon { + margin-right: 0; + } +} + +.breadcrumb-listing-dropdown { + box-shadow: $bs-med; + overflow: hidden; + min-height: 100px; + width: 240px; + display: none; + position: absolute; + z-index: 80; + right: -$-m; + .breadcrumb-listing-search .svg-icon { + position: absolute; + left: $-s; + top: 11px; + fill: #888; + pointer-events: none; + } + .breadcrumb-listing-entity-list { + max-height: 400px; + overflow-y: scroll; + text-align: left; + } + input { + padding-left: $-xl; + border-radius: 0; + border: 0; + border-bottom: 1px solid #DDD; + } +} + +@include smaller-than($m) { + .breadcrumb-listing-dropdown { + position: fixed; + right: auto; + left: $-m; + } + .breadcrumb-listing-dropdown .breadcrumb-listing-entity-list { + max-height: 240px; + } +} + .faded { a, button, span, span > div { color: #666; @@ -175,20 +334,9 @@ header .search-box { padding: $-s; } -.faded-small { - color: #000; - fill: #000; - font-size: 0.9em; - background-color: $primary-faded; -} - -.toolbar-container { - background-color: #FFF; -} - -.breadcrumbs .text-button, .action-buttons .text-button { +.action-buttons .text-button { display: inline-block; - padding: $-s; + padding: $-xs $-s; &:last-child { padding-right: 0; } @@ -217,28 +365,12 @@ header .search-box { } @include smaller-than($m) { - .breadcrumbs .text-button, .action-buttons .text-button { + .action-buttons .text-button { padding: $-xs $-xs; } .action-buttons .dropdown-container:last-child a { padding-left: $-xs; } - .breadcrumbs .text-button { - font-size: 0; - } - .breadcrumbs .text-button svg { - font-size: $fs-m; - } - .breadcrumbs a i { - font-size: $fs-m; - padding-right: 0; - } - .breadcrumbs span.sep { - padding: 0 $-xxs; - } - .toolbar .col-xs-1:first-child { - padding-right: 0; - } } .nav-tabs { @@ -253,7 +385,4 @@ header .search-box { border-bottom: 2px solid $primary; } } -} -.faded-small .nav-tabs a { - padding: $-s $-m; } \ No newline at end of file diff --git a/resources/assets/sass/_html.scss b/resources/assets/sass/_html.scss index 65f05a71d5c..7c3a3c49b41 100644 --- a/resources/assets/sass/_html.scss +++ b/resources/assets/sass/_html.scss @@ -3,27 +3,18 @@ } html { - background-color: #FFFFFF; height: 100%; overflow-y: scroll; + background-color: #F2F2F2; &.flexbox { overflow-y: hidden; } - &.shaded { - background-color: #F2F2F2; - } } body { font-size: $fs-m; line-height: 1.6; - color: #616161; + color: #444; -webkit-font-smoothing: antialiased; - &.shaded { - background-color: #F2F2F2; - } -} - -button { - font-size: 100%; + background-color: #F2F2F2; } \ No newline at end of file diff --git a/resources/assets/sass/_layout.scss b/resources/assets/sass/_layout.scss new file mode 100644 index 00000000000..13704893520 --- /dev/null +++ b/resources/assets/sass/_layout.scss @@ -0,0 +1,312 @@ + +/** + * Generic content container + */ +.container { + max-width: $xxl; + margin-left: auto; + margin-right: auto; + padding-left: $-m; + padding-right: $-m; + &.small { + max-width: 840px; + } + &.very-small { + max-width: 480px; + } +} + +/** + * Core grid layout system + */ +.grid { + display: grid; + grid-column-gap: $-l; + grid-row-gap: $-l; + &.half { + grid-template-columns: 1fr 1fr; + } + &.third { + grid-template-columns: 1fr 1fr 1fr; + } + &.left-focus { + grid-template-columns: 2fr 1fr; + } + &.right-focus { + grid-template-columns: 1fr 3fr; + } + &.gap-y-xs { + grid-row-gap: $-xs; + } + &.gap-xl { + grid-column-gap: $-xl; + grid-row-gap: $-xl; + } + &.gap-xxl { + grid-column-gap: $-xxl; + grid-row-gap: $-xxl; + } + &.v-center { + align-items: center; + } + &.no-gap { + grid-row-gap: 0; + grid-column-gap: 0; + } + &.no-row-gap { + grid-row-gap: 0; + } +} + +@include smaller-than($m) { + .grid.third { + grid-template-columns: 1fr 1fr; + } + .grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) { + grid-template-columns: 1fr; + } + .grid.half.collapse-xs { + grid-template-columns: 1fr 1fr; + } + .grid.gap-xl { + grid-column-gap: $-m; + grid-row-gap: $-m; + } + .grid.right-focus.reverse-collapse > *:nth-child(2) { + order: 0; + } + .grid.right-focus.reverse-collapse > *:nth-child(1) { + order: 1; + } +} + +@include smaller-than($s) { + .grid.third { + grid-template-columns: 1fr; + } +} + +@include smaller-than($xs) { + .grid.half.collapse-xs { + grid-template-columns: 1fr; + } +} + +/** + * Flexbox layout system + */ +body.flexbox { + display: flex; + flex-direction: column; + align-items: stretch; + height: 100%; + min-height: 100%; + max-height: 100%; + overflow: hidden; + #content { + flex: 1; + display: flex; + min-height: 0; + } +} + +.flex-fill { + display: flex; + align-items: stretch; + min-height: 0; + max-width: 100%; + position: relative; +} + +.flex { + min-height: 0; + flex: 1; +} + + +/** + * Display and float utilities + */ +.block { + display: block; + position: relative; +} + +.inline { + display: inline; +} + +.block.inline { + display: inline-block; +} + +.float { + float: left; + &.right { + float: right; + } +} + +/** + * Visibility + */ +@each $sizeLetter, $size in $screen-sizes { + @include smaller-than($size) { + .hide-under-#{$sizeLetter} { + display: none !important; + } + } + @include larger-than($size) { + .hide-over-#{$sizeLetter} { + display: none !important; + } + } +} + +/** + * Inline content columns + */ +.dual-column-content { + columns: 2; +} + +@include smaller-than($m) { + .dual-column-content { + columns: 1; + } +} + + +/** + * Fixes + */ +.clearfix:before, +.clearfix:after { + content: " "; + display: table; +} +.clearfix:after { + clear: both; +} + +/** + * View Layouts + */ +.tri-layout-container { + display: grid; + margin-left: $-xl; + margin-right: $-xl; + grid-template-columns: 1fr 4fr 1fr; + grid-template-areas: "a b c"; + grid-column-gap: $-xxl; + .tri-layout-right { + grid-area: c; + min-width: 0; + } + .tri-layout-left { + grid-area: a; + min-width: 0; + } + .tri-layout-middle { + grid-area: b; + padding-top: $-m; + } +} +@include smaller-than($xxl) { + .tri-layout-container { + grid-template-areas: "c b b" + "a b b"; + grid-template-columns: 1fr 3fr; + grid-template-rows: max-content min-content; + padding-right: $-l; + } +} +@include larger-than($xxl) { + .tri-layout-left-contents, .tri-layout-right-contents { + padding: $-m; + position: sticky; + top: $-m; + max-height: 100vh; + min-height: 50vh; + overflow-y: scroll; + overflow-x: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + } + .tri-layout-middle-contents { + max-width: 940px; + margin: 0 auto; + } +} + +@include smaller-than($l) { + .tri-layout-container { + grid-template-areas: none; + grid-template-columns: 1fr; + grid-column-gap: 0; + padding-right: $-xs; + padding-left: $-xs; + .tri-layout-left-contents, .tri-layout-right-contents { + padding-left: $-m; + padding-right: $-m; + } + .tri-layout-right-contents > div, .tri-layout-left-contents > div { + opacity: 0.6; + z-index: 0; + } + .tri-layout-left > *, .tri-layout-right > * { + display: none; + pointer-events: none; + } + .tri-layout-left, .tri-layout-right { + grid-area: none; + grid-column: 1/1; + grid-row: 1; + padding-top: 0 !important; + } + .tri-layout-middle { + grid-area: none; + grid-row: 3; + grid-column: 1/1; + z-index: 1; + overflow: hidden; + transition: transform ease-in-out 240ms; + } + .tri-layout-left { + grid-row: 2; + } + &.show-info { + overflow: hidden; + .tri-layout-middle { + display: none; + } + .tri-layout-right > *, .tri-layout-left > * { + display: block; + pointer-events: auto; + } + } + } +} +@include larger-than($l) { + .tri-layout-mobile-tabs { + display: none; + } +} + +@include smaller-than($m) { + .tri-layout-container { + margin-left: 0; + margin-right: 0; + } +} + +.tri-layout-left-contents > div, .tri-layout-right-contents > div { + opacity: 0.6; + transition: opacity ease-in-out 120ms; + &:hover { + opacity: 1; + } +} \ No newline at end of file diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index 18a7ea9cee0..dc4dc8816cd 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -1,182 +1,217 @@ -.page-list { - h4 { - margin: $-l 0 $-xs 0; - font-size: 1.666em; + +.book-contents .entity-list-item { + .icon { + width: 4px; + border-radius: 1px; + justify-self: stretch; + align-self: stretch; + height: auto; + margin-right: $-l; } - a.chapter { - color: $color-chapter; + .icon:after { + opacity: 0.5; } - .inset-list { + .icon svg { display: none; - overflow: hidden; } - h5 { - display: block; - margin: $-s 0 0 0; - border-left: 5px solid $color-page; - padding: $-xs 0 $-xs $-m; - font-size: 1.1em; - font-weight: normal; - &.draft { - border-left-color: $color-page-draft; - } - } - .entity-list-item { - margin-bottom: $-m; - } - hr { - margin-top: 0; - } - .page, .chapter, .book { - padding-left: $-l; + p { + margin-bottom: 0; } - .page { - border-left: 5px solid $color-page; + .inner-page { + padding-top: 0; + padding-bottom: 0; } - .page.draft { - border-left: 5px solid $color-page-draft; - .text-page { - color: $color-page-draft; - fill: $color-page-draft; +} + +.entity-list-item + .chapter-expansion { + display: flex; + padding: 0 $-m $-m $-m; + align-items: center; + border: 0; + width: 100%; + position: relative; + > .icon { + width: 4px; + height: auto; + border-radius: 0 0 1px 1px; + align-self: stretch; + flex-shrink: 0; + &:before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1px; + background-color: currentColor; + content: ''; + opacity: 0.5; + } + &:after { + opacity: 0.5; } } - .chapter { - border-left: 5px solid $color-chapter; + .icon svg { + display: none; } - .book { - border-left: 5px solid $color-book; + > .content { + flex: 1; } - .meta { - margin-top: -$-m; - font-size: 0.95em; + .chapter-expansion-toggle { + border-radius: 0 4px 4px 0; + padding: $-xs $-m; } - .meta span { - margin-right: $-s; + .chapter-expansion-toggle:hover { + background-color: rgba(0, 0, 0, 0.06); } } -@include smaller-than($s) { - .page-list h4 { - font-size: 1.333em; +.entity-list-item.has-children { + padding-bottom: 0; + > .icon { + border-radius: 4px 4px 0 0; + } +} + +.inset-list { + display: none; + .entity-list-item-name { + font-size: 1rem; + } + .entity-list-item-children { + padding-top: 0; + padding-bottom: 0; } } .sidebar-page-nav { - $nav-indent: $-s; + $nav-indent: $-m; list-style: none; - margin: $-s 0 $-m 2px; - border-left: 2px dotted #BBB; + margin: $-s 0 $-m $-xs; + position: relative; + &:after { + content: ''; + display: block; + position: absolute; + left: 0; + background-color: rgba(0, 0, 0, 0.2); + width: 2px; + top: 5px; + bottom: 5px; + z-index: 0; + } li { - padding-left: $-s; margin-bottom: 4px; font-size: 0.95em; + position: relative; } .h1 { - margin-left: -2px; + padding-left: $nav-indent; } .h2 { - margin-left: -2px; + padding-left: $nav-indent; } .h3 { - margin-left: $nav-indent; + padding-left: $nav-indent * 2; } .h4 { - margin-left: $nav-indent*2; + padding-left: $nav-indent * 2.5; } .h5 { - margin-left: $nav-indent*3; + padding-left: $nav-indent*3; } .h6 { - margin-left: $nav-indent*4; + padding-left: $nav-indent*3.5; } .current-heading { font-weight: bold; } + li:not(.current-heading) .sidebar-page-nav-bullet { + background-color: #BBB !important; + } + .sidebar-page-nav-bullet { + width: 6px; + height: 6px; + position: absolute; + left: -2px; + top: 30%; + border-radius: 50%; + box-shadow: 0 0 0 6px #F2F2F2; + z-index: 1; + } } // Sidebar list -.book-tree { - transition: ease-in-out 240ms; - transition-property: right, border; -} -.book-tree h4 { - padding: $-m $-s 0 $-s; - i { - padding-right: $-s; - } -} -.book-tree .sidebar-page-list { +.book-tree .sidebar-page-list { list-style: none; - margin: $-xs 0 0; + margin: $-xs -$-s 0 -$-s; padding-left: 0; - border-left: 5px solid $color-book; - li a { - display: block; - border-bottom: none; - padding: $-xs 0 $-xs $-s; - &:hover { - text-decoration: none; - } - } - li a i { - padding-right: $-xs + 2px; - } - li, a { + padding-right: 0; + position: relative; + + &:after, .sub-menu:after { + content: ''; display: block; + position: absolute; + left: $-m; + top: 1rem; + bottom: 1rem; + border-left: 4px solid rgba(0, 0, 0, 0.1); + z-index: 0; } - a.bold { - color: #EEE !important; - fill: #EEE !important; - } + ul { list-style: none; - margin: 0; + padding-left: 1rem; + padding-right: 0; } - .book { - color: $color-book !important; - fill: $color-book !important; - &.selected { - background-color: rgba($color-book, 0.29); + .entity-list-item { + padding-top: $-xxs; + padding-bottom: $-xxs; + .content { + padding-top: $-xs; + padding-bottom: $-xs; + max-width: calc(100% - 20px); } } - .chapter { - color: $color-chapter !important; - fill: $color-chapter !important; - &.selected { - background-color: rgba($color-chapter, 0.12); - } + .entity-list-item.no-hover { + margin-top: -$-xs; + padding-right: 0; } - .page { - color: $color-page !important; - fill: $color-page !important; - border-bottom: none; - &.selected { - background-color: rgba($color-page, 0.1); - } + .entity-list-item-name { + font-size: 1em; + margin: 0; } - [chapter-toggle] { - padding-left: $-s; + .chapter-child-menu { + font-size: .8rem; + margin-top: -.2rem; + margin-left: -1rem; } - .list-item-chapter { - border-left: 5px solid $color-chapter; - margin: 10px 10px; - display: block; + [chapter-toggle] { + padding-left: .7rem; + padding-bottom: .2rem; } - .list-item-page { - border-bottom: none; - border-left: 5px solid $color-page; - margin: 10px 10px; + .entity-list-item .icon { + z-index: 2; + width: 4px; + height: auto; + align-self: stretch; + flex-shrink: 0; + border-radius: 1px; + opacity: 0.6; } - .list-item-page.draft { - border-left: 5px solid $color-page-draft; + .entity-list-item .icon:after { + opacity: 1; } - .page.draft .page, .list-item-page.draft a.page { - color: $color-page-draft !important; - fill: $color-page-draft !important; + .entity-list-item .icon svg { + display: none; } - .sub-menu { +} + +.chapter-child-menu { + ul.sub-menu { display: none; padding-left: 0; + position: relative; } [chapter-toggle].open + .sub-menu { display: block; @@ -186,26 +221,41 @@ // Sortable Lists .sortable-page-list, .sortable-page-list ul { list-style: none; - background-color: #FFF; } .sort-box { margin-bottom: $-m; - padding: 0 $-l 0 $-l; - border-left: 4px solid $color-book; + border: 2px solid rgba($color-book, 0.6); + padding: $-m $-xl; + border-radius: 4px; +} +.sort-box-options { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} +.sort-box-options .button { + margin-left: 0; } .sortable-page-list { margin-left: 0; + padding: 0; + .entity-list-item > span:first-child { + align-self: flex-start; + } + .entity-list-item > div { + display: block; + flex: 1; + } > ul { margin-left: 0; } ul { - margin-bottom: 0; + margin-bottom: $-m; margin-top: 0; - box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.1); + padding-left: $-m; } li { border: 1px solid #DDD; - padding: $-xs $-s; margin-top: -1px; min-height: 38px; &.text-chapter { @@ -228,18 +278,26 @@ .activity-list-item { padding: $-s 0; + display: grid; + grid-template-columns: min-content 1fr; + grid-column-gap: $-m; color: #888; fill: #888; - border-bottom: 1px solid #EEE; font-size: 0.9em; - .left { - float: left; - } - .left + .right { - margin-left: 30px + $-s; - } - &:last-of-type { - border-bottom: 0; +} +.card .activity-list-item { + padding: $-s $-m; +} + +.user-list-item { + display: inline-grid; + padding: $-s; + grid-template-columns: min-content 1fr; + grid-column-gap: $-m; + font-size: 0.9em; + align-items: center; + > div:first-child { + line-height: 0; } } @@ -280,10 +338,8 @@ ul.pagination { margin: 0; } -.entity-list { - > div { - padding: $-m 0; - } +.entity-list, .icon-list { + margin: 0 (-$-m); h4 { margin: 0; } @@ -302,15 +358,125 @@ ul.pagination { color: $color-page-draft; fill: $color-page-draft; } + > .dropdown-container { + display: block; + } +} + +.icon-list hr { + margin: $-s $-m; + max-width: 140px; + opacity: 0.25; + height: 1.1px; +} + +.icon-list hr + hr, .icon-list hr:first-child, .icon-list hr:last-child { + display: none; +} + +.entity-list-item, .icon-list-item { + padding: $-s $-m; + display: flex; + align-items: center; + background-color: transparent; + border: 0; + width: 100%; + position: relative; + word-break: break-word; + h4 a { + color: #666; + } + > span:first-child { + margin-right: $-m; + flex-basis: 1.88em; + flex: none; + } + > span:last-child { + flex: 1; + text-align: left; + } + &:not(.no-hover) { + cursor: pointer; + } + &:not(.no-hover):hover { + text-decoration: none; + background-color: rgba(0, 0, 0, 0.1); + border-radius: 4px; + } + &.outline-hover { + border: 1px solid transparent; + } + &.outline-hover:hover { + background-color: transparent; + border-color: rgba(0, 0, 0, 0.1); + } } -.card .entity-list-item, .card .activity-list-item { - padding-left: $-m; - padding-right: $-m; +.entity-list-item-path-sep { + display: inline-block; + vertical-align: top; + position: relative; + top: 1px; + svg { + margin-right: 0; + } +} + +.card .entity-list-item:not(.no-hover):hover { + background-color: #F2F2F2; +} +.card .entity-list-item .entity-list-item:hover { + background-color: #EEEEEE; +} + +.entity-list-item-children { + padding: $-m; + > div { + overflow: hidden; + padding: $-xs 0; + margin-top: -$-xs; + } + .entity-chip { + text-overflow: ellipsis; + height: 2.5em; + overflow: hidden; + text-align: left; + display: block; + white-space: nowrap; + } +} + +.entity-list-item-image { + align-self: stretch; + width: 140px; + flex: none; + background-size: cover; + background-position: 50% 50%; + border-radius: 3px; + position: relative; + margin-right: $-l; + + .svg-icon { + color: #FFF; + fill: #FFF; + font-size: 1.66rem; + margin-right: 0; + position: absolute; + bottom: $-xs; + left: $-xs; + } + + @include smaller-than($m) { + width: 80px; + } +} + +.chapter > .entity-list-item-image { + width: 60px; } .entity-list.compact { - font-size: 0.6em; + font-size: 0.6 * $fs-m; h4, a { line-height: 1.2; } @@ -331,6 +497,11 @@ ul.pagination { hr { margin: 0; } + @include smaller-than($m) { + h4 { + font-size: 1.666em; + } + } } .dropdown-container { @@ -363,9 +534,8 @@ ul.pagination { color: #999; fill: #999; } - li.padded { - padding: $-xs $-m; - line-height: 1.2; + li.active a { + font-weight: 600; } a, button { display: block; @@ -396,7 +566,10 @@ ul.pagination { .featured-image-container { position: relative; overflow: hidden; - background: #F2F2F2; + min-height: 140px; + background-size: cover; + background-position: 50% 50%; + transition: opacity ease-in-out 240ms; a { display: block; } @@ -405,11 +578,46 @@ ul.pagination { width: 100%; max-width: 100%; height: auto; - transition: all .5s ease-in-out; } - img:hover { - transform: scale(1.15); - opacity: .5; +} +.featured-image-container-wrap { + position: relative; + .svg-icon { + color: #FFF; + fill: #FFF; + font-size: 2rem; + margin-right: 0; + position: absolute; + bottom: 10px; + left: 6px; } } +.grid-card:hover .featured-image-container { + opacity: .5; +} + +.action-link-list { + //padding: $-s 0; +} +.action-link { + background: transparent; + border: none; + color: currentColor; + padding: $-m 0; +} +.active-link-list { + a { + display: inline-block; + padding: $-s; + } + a:not(.active) { + color: #444; + fill: #444; + } + a:hover { + background-color: rgba(0, 0, 0, 0.05); + border-radius: 3px; + text-decoration: none; + } +} \ No newline at end of file diff --git a/resources/assets/sass/_mixins.scss b/resources/assets/sass/_mixins.scss index 3d3101ca713..1c45ebd3080 100644 --- a/resources/assets/sass/_mixins.scss +++ b/resources/assets/sass/_mixins.scss @@ -5,12 +5,6 @@ @mixin larger-than($size) { @media screen and (min-width: $size) { @content; } } -@mixin clearfix() { - &:after { - display: block; - content: ''; - font-size: 0; - clear: both; - position: relative; - } +@mixin between($min, $max) { + @media screen and (min-width: $min) and (max-width: $max) { @content; } } diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss index 84280319deb..969682c3ba8 100755 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -3,12 +3,12 @@ flex-direction: column; align-items: stretch; overflow: hidden; - .faded-small { - height: auto; - } + background-color: #FFF; + .edit-area { flex: 1; flex-direction: column; + z-index: 1; } .mce-tinymce { @@ -20,6 +20,39 @@ } } +@include smaller-than($l) { + .page-edit-toolbar { + overflow-x: scroll; + overflow-y: visible; + z-index: 4; + } + .page-edit-toolbar .grid.third { + display: block; + white-space: nowrap; + > div { + display: inline-block; + } + } +} + +@include smaller-than($l) { + .page-edit-toolbar #save-button { + position: fixed; + z-index: 30; + background-color: #FFF; + border-radius: 50%; + width: 42px; + height: 42px; + font-size: 16px; + right: $-m; + bottom: $-xs; + box-shadow: $bs-med; + span { + display: none; + } + } +} + .draft-notification { pointer-events: none; transform: scale(0); @@ -38,11 +71,7 @@ width: 100%; max-width: 840px; margin: 0 auto; - margin-top: $-xxl; overflow-wrap: break-word; - &.flex { - margin-top: $-m; - } .align-left { text-align: left; } @@ -248,13 +277,6 @@ min-height: 0px; overflow-y: scroll; } - div[toolbox-tab-content] .padded { - flex: 1; - padding-top: 0; - } - div[toolbox-tab-content] .padded.files { - overflow-x: hidden; - } h4 { font-size: 24px; margin: $-m 0 0 0; @@ -349,16 +371,10 @@ } } -.comments-container { - width: 100%; - border-top: 1px solid #DDD; - margin-top: $-xl; - margin-bottom: $-m; - h5 { - color: #888; - font-weight: normal; - margin-top: 0.5em; - } +.comments-container h5 { + color: #888; + font-weight: normal; + margin-top: 0.5em; } .comment-editor .CodeMirror, .comment-editor .CodeMirror-scroll { @@ -370,4 +386,60 @@ .mce-open { display: none; } +} + +.entity-list-item > span:first-child, .icon-list-item > span:first-child, .chapter-expansion > .icon { + font-size: 0.8rem; + width: 1.88em; + height: 1.88em; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + border-radius: 1em; + position: relative; + overflow: hidden; + svg { + margin: 0; + bottom: 0; + } + &:after { + content: ''; + position: absolute; + background-color: currentColor; + opacity: 0.2; + left: 0; + top: 0; + width: 100%; + height: 100%; + } +} + +.entity-chip { + display: inline-block; + align-items: center; + justify-content: center; + text-align: center; + font-size: 0.9em; + border-radius: 3px; + position: relative; + overflow: hidden; + padding: $-xs $-s; + fill: currentColor; + opacity: 0.85; + transition: opacity ease-in-out 120ms; + &:after { + content: ''; + position: absolute; + background-color: currentColor; + opacity: 0.15; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + &:hover { + text-decoration: none; + opacity: 1; + } } \ No newline at end of file diff --git a/resources/assets/sass/_spacing.scss b/resources/assets/sass/_spacing.scss new file mode 100644 index 00000000000..69ed5a2d3c0 --- /dev/null +++ b/resources/assets/sass/_spacing.scss @@ -0,0 +1,32 @@ +// Here we generate spacing utility classes for our sizes for all box sides and axis. +// These will output to classes like .px-m (Padding on x-axis, medium size) or .mr-l (Margin right, large size) + +@mixin spacing($prop, $propLetter) { + @each $sizeLetter, $size in $spacing { + .#{$propLetter}-#{$sizeLetter} { + #{$prop}: $size !important; + } + .#{$propLetter}x-#{$sizeLetter} { + #{$prop}-left: $size !important; + #{$prop}-right: $size !important; + } + .#{$propLetter}y-#{$sizeLetter} { + #{$prop}-top: $size !important; + #{$prop}-bottom: $size !important; + } + .#{$propLetter}t-#{$sizeLetter} { + #{$prop}-top: $size !important; + } + .#{$propLetter}r-#{$sizeLetter} { + #{$prop}-right: $size !important; + } + .#{$propLetter}b-#{$sizeLetter} { + #{$prop}-bottom: $size !important; + } + .#{$propLetter}l-#{$sizeLetter} { + #{$prop}-left: $size !important; + } + } +} +@include spacing('margin', 'm') +@include spacing('padding', 'p') \ No newline at end of file diff --git a/resources/assets/sass/_tables.scss b/resources/assets/sass/_tables.scss index ec24e2fa64f..a1a2fef0a44 100644 --- a/resources/assets/sass/_tables.scss +++ b/resources/assets/sass/_tables.scss @@ -19,13 +19,13 @@ table { table.table { width: 100%; - tr { - border-bottom: 1px solid #DDD; + tr td, tr th { + border-bottom: 1px solid rgba(0, 0, 0, 0.05); } th, td { text-align: left; border: none; - padding: $-xs $-xs; + padding: $-s $-s; vertical-align: middle; margin: 0; } @@ -44,6 +44,9 @@ table.table { td.actions { overflow: visible; } + a { + display: inline-block; + } } table.no-style { diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index 0063c4672cc..dd1c74d24d2 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -42,7 +42,7 @@ h1, h2, h3, h4, h5, h6 { font-weight: 400; position: relative; display: block; - color: #555; + color: #222; .subheader { font-size: 0.5em; line-height: 1em; @@ -79,10 +79,18 @@ h5, h6 { } } +.list-heading { + font-size: 2rem; +} + +h2.list-heading { + font-size: 1.333rem; +} + /* * Link styling */ -a, .link { +a { color: $primary; cursor: pointer; text-decoration: none; @@ -141,11 +149,8 @@ em, i, .italic { } small, p.small, span.small, .text-small { - font-size: 0.8em; - color: lighten($text-dark, 20%); - small, p.small, span.small, .text-small { - font-size: 1em; - } + font-size: 0.75rem; + color: lighten($text-dark, 10%); } sup, .superscript { @@ -233,106 +238,6 @@ pre code { display: block; line-height: 1.6; } -/* - * Text colors - */ -p.pos, p .pos, span.pos, .text-pos { - color: $positive; - fill: $positive; - &:hover { - color: $positive; - fill: $positive; - } -} - -p.neg, p .neg, span.neg, .text-neg { - color: $negative; - fill: $negative; - &:hover { - color: $negative; - fill: $negative; - } -} - -p.muted, p .muted, span.muted, .text-muted { - color: lighten($text-dark, 26%); - fill: lighten($text-dark, 26%); - &.small, .small { - color: lighten($text-dark, 32%); - fill: lighten($text-dark, 32%); - } -} - -p.primary, p .primary, span.primary, .text-primary { - color: $primary; - fill: $primary; - &:hover { - color: $primary; - fill: $primary; - } -} - -p.secondary, p .secondary, span.secondary, .text-secondary { - color: $secondary; - fill: $secondary; - &:hover { - color: $secondary; - fill: $secondary; - } -} - -.text-bookshelf { - color: $color-bookshelf; - fill: $color-bookshelf; - &:hover { - color: $color-bookshelf; - fill: $color-bookshelf; - } -} -.text-book { - color: $color-book; - fill: $color-book; - &:hover { - color: $color-book; - fill: $color-book; - } -} -.text-page { - color: $color-page; - fill: $color-page; - &:hover { - color: $color-page; - fill: $color-page; - } - &.draft { - color: $color-page-draft; - fill: $color-page-draft; - } - &.draft:hover { - color: $color-page-draft; - fill: $color-page-draft; - } -} -.text-chapter { - color: $color-chapter; - fill: $color-chapter; - &:hover { - color: $color-chapter; - fill: $color-chapter; - } -} -.faded .text-book:hover { - color: $color-book !important; - fill: $color-book !important; -} -.faded .text-chapter:hover { - color: $color-chapter !important; - fill: $color-chapter !important; -} -.faded .text-page:hover { - color: $color-page !important; - fill: $color-page !important; -} span.highlight { //background-color: rgba($primary, 0.2); @@ -435,10 +340,6 @@ span.sep { /** * Icons */ -i { - padding-right: $-xs; -} - .svg-icon { width: 1em; height: 1em; @@ -446,5 +347,6 @@ i { position: relative; bottom: -0.105em; margin-right: $-xs; + pointer-events: none; } diff --git a/resources/assets/sass/_tinymce.scss b/resources/assets/sass/_tinymce.scss index c758619d693..2dbf6916430 100644 --- a/resources/assets/sass/_tinymce.scss +++ b/resources/assets/sass/_tinymce.scss @@ -21,6 +21,13 @@ text-align: center; } +@include smaller-than($l) { + .mce-container-body.mce-flow-layout { + overflow-x: scroll; + white-space: nowrap; + } +} + .edit-area.flex > div > .mce-tinymce.mce-container.mce-panel { flex: 1 1 auto; display: flex !important; diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss index 006d1b3f08d..25b8e09b75f 100644 --- a/resources/assets/sass/_variables.scss +++ b/resources/assets/sass/_variables.scss @@ -1,14 +1,12 @@ // Variables /////////////// -// Sizes -$max-width: 1400px; - // Screen breakpoints +$xxl: 1400px; $xl: 1100px; $ipad-width: 1028px; // Is actually 1024 but we go over to ensure functionality. $l: 1000px; -$m: 800px; +$m: 880px; $s: 600px; $xs: 400px; $xxs: 360px; @@ -16,6 +14,9 @@ $screen-lg: 1200px; $screen-md: 992px; $screen-sm: 768px; +// List of screen sizes +$screen-sizes: (('xxs', $xxs), ('xs', $xs), ('s', $s), ('m', $m), ('l', $l), ('xl', $xl)); + // Spacing (Margins+Padding) $-xxxl: 64px; $-xxl: 48px; @@ -26,6 +27,9 @@ $-s: 12px; $-xs: 6px; $-xxs: 3px; +// List of our spacing sizes +$spacing: (('none', 0), ('xxs', $-xxs), ('xs', $-xs), ('s', $-s), ('m', $-m), ('l', $-l), ('xl', $-xl), ('xxl', $-xxl)); + // Fonts $text: -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Roboto", "Cantarell", @@ -33,8 +37,8 @@ $text: -apple-system, BlinkMacSystemFont, sans-serif; $mono: "Lucida Console", "DejaVu Sans Mono", "Ubunto Mono", Monaco, monospace; $heading: $text; -$fs-m: 15px; -$fs-s: 14px; +$fs-m: 14px; +$fs-s: 12px; // Colours $primary: #0288D1; @@ -49,7 +53,7 @@ $primary-faded: rgba(21, 101, 192, 0.15); // Item Colors $color-bookshelf: #af5a5a; $color-book: #009688; -$color-chapter: #ef7c3c; +$color-chapter: #d7804a; $color-page: $primary; $color-page-draft: #9A60DA; @@ -60,5 +64,5 @@ $text-light: #EEE; // Shadows $bs-light: 0 0 4px 1px #CCC; $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26); -$bs-card: 0 1px 3px 1px rgba(76, 76, 76, 0.26), 0 1px 12px 0px rgba(76, 76, 76, 0.2); +$bs-card: 0 1px 6px -1px rgba(0, 0, 0, 0.1); $bs-hover: 0 2px 2px 1px rgba(0,0,0,.13); \ No newline at end of file diff --git a/resources/assets/sass/export-styles.scss b/resources/assets/sass/export-styles.scss index cc90d5372e4..4cc782dc0e9 100644 --- a/resources/assets/sass/export-styles.scss +++ b/resources/assets/sass/export-styles.scss @@ -1,8 +1,9 @@ @import "variables"; @import "mixins"; +@import "spacing"; @import "html"; @import "text"; -@import "grid"; +@import "layout"; @import "blocks"; @import "forms"; @import "tables"; @@ -12,6 +13,9 @@ body { font-family: 'DejaVu Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Roboto", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + background-color: #FFF; + margin: 0; + padding: 0; } table { @@ -19,6 +23,10 @@ table { border-collapse: collapse; } +.page-content { + overflow: hidden; +} + // Prevent code block overflow on export pre { padding-left: 12px; diff --git a/resources/assets/sass/print-styles.scss b/resources/assets/sass/print-styles.scss index c67f9864249..44107f2d4d5 100644 --- a/resources/assets/sass/print-styles.scss +++ b/resources/assets/sass/print-styles.scss @@ -8,10 +8,6 @@ body { font-size: 12px; } -.faded-small { - display: none; -} - .page-content { margin: 0 auto; } diff --git a/resources/assets/sass/styles.scss b/resources/assets/sass/styles.scss index 49ef77f3938..424074a0d27 100644 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@ -1,9 +1,11 @@ @import "reset"; @import "variables"; @import "mixins"; +@import "spacing"; @import "html"; @import "text"; -@import "grid"; +@import "colors"; +@import "layout"; @import "blocks"; @import "buttons"; @import "tables"; @@ -94,17 +96,6 @@ $loadingSize: 10px; } } - -// Search results -.search-results > h3 a { - font-size: 0.66em; - color: $primary; - padding-left: $-m; - i { - padding-right: $-s; - } -} - // Back to top link $btt-size: 40px; [back-to-top] { @@ -186,22 +177,28 @@ $btt-size: 40px; overflow-y: scroll; height: 400px; background-color: #EEEEEE; + margin-right: 0; + margin-left: 0; + } + .entity-list-item { + background-color: #FFF; + } + .entity-list-item p { + margin-bottom: 0; + } + .entity-list-item.selected { + background-color: rgba(0, 0, 0, 0.15) !important; } .loading { height: 400px; padding-top: $-l; } - .entity-list > p { - text-align: center; - padding-top: $-l; - font-size: 1.333em; - } - .entity-list > div { - padding-left: $-m; - padding-right: $-m; - background-color: #FFF; - transition: all ease-in-out 120ms; - cursor: pointer; + .entity-selector-add button { + margin: 0; + display: block; + width: 100%; + border: 0; + border-top: 1px solid #DDD; } &.compact { font-size: 10px; @@ -211,12 +208,6 @@ $btt-size: 40px; } } -.entity-list-item.selected { - h3, i, p ,a, span { - color: #EEE; - } -} - .scroll-box { max-height: 250px; overflow-y: scroll; @@ -254,3 +245,39 @@ $btt-size: 40px; height:100%; z-index: 150; } + +.list-sort-container { + display: inline-block; + form { + display: inline-block; + } + .list-sort { + display: inline-grid; + margin-left: $-s; + grid-template-columns: 120px 40px; + border: 2px solid #DDD; + border-radius: 4px; + } + .list-sort-label { + font-weight: bold; + display: inline-block; + color: #888; + } + .list-sort-type { + text-align: left; + } + .list-sort-type, .list-sort-dir { + padding: $-xs $-s; + cursor: pointer; + } + .list-sort-dir { + border-left: 2px solid #DDD; + fill: #888; + .svg-icon { + transition: transform ease-in-out 120ms; + } + &:hover .svg-icon { + transform: rotate(180deg); + } + } +} \ No newline at end of file diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index ac2edc621f9..ed880afcf9a 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -11,6 +11,7 @@ 'save' => 'Save', 'continue' => 'Continue', 'select' => 'Select', + 'toggle_all' => 'Toggle All', 'more' => 'More', // Form Labels @@ -23,6 +24,7 @@ // Actions 'actions' => 'Actions', 'view' => 'View', + 'view_all' => 'View All', 'create' => 'Create', 'update' => 'Update', 'edit' => 'Edit', @@ -37,6 +39,11 @@ 'remove' => 'Remove', 'add' => 'Add', + // Sort Options + 'sort_name' => 'Name', + 'sort_created_at' => 'Created Date', + 'sort_updated_at' => 'Updated Date', + // Misc 'deleted_user' => 'Deleted User', 'no_activity' => 'No activity to show', @@ -53,7 +60,11 @@ 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + // Layout tabs + 'tab_info' => 'Info', + 'tab_content' => 'Content', + // Email Content 'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:', 'email_rights' => 'All rights reserved', -]; \ No newline at end of file +]; diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 2a64f57a370..c2c15d72f26 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -11,6 +11,7 @@ 'recently_updated_pages' => 'Recently Updated Pages', 'recently_created_chapters' => 'Recently Created Chapters', 'recently_created_books' => 'Recently Created Books', + 'recently_created_shelves' => 'Recently Created Shelves', 'recently_update' => 'Recently Updated', 'recently_viewed' => 'Recently Viewed', 'recent_activity' => 'Recent Activity', @@ -67,6 +68,7 @@ // Shelves 'shelf' => 'Shelf', 'shelves' => 'Shelves', + 'x_shelves' => ':count Shelf|:count Shelves', 'shelves_long' => 'Bookshelves', 'shelves_empty' => 'No shelves have been created', 'shelves_create' => 'Create New Shelf', @@ -117,7 +119,6 @@ 'books_permissions_updated' => 'Book Permissions Updated', 'books_empty_contents' => 'No pages or chapters have been created for this book.', 'books_empty_create_page' => 'Create a new page', - 'books_empty_or' => 'or', 'books_empty_sort_current_book' => 'Sort the current book', 'books_empty_add_chapter' => 'Add a chapter', 'books_permissions_active' => 'Book Permissions Active', @@ -125,6 +126,11 @@ 'books_navigation' => 'Book Navigation', 'books_sort' => 'Sort Book Contents', 'books_sort_named' => 'Sort Book :bookName', + 'books_sort_name' => 'Sort by Name', + 'books_sort_created' => 'Sort by Created Date', + 'books_sort_updated' => 'Sort by Updated Date', + 'books_sort_chapters_first' => 'Chapters First', + 'books_sort_chapters_last' => 'Chapters Last', 'books_sort_show_other' => 'Show Other Books', 'books_sort_save' => 'Save New Order', @@ -202,6 +208,8 @@ 'pages_revisions_created_by' => 'Created By', 'pages_revisions_date' => 'Revision Date', 'pages_revisions_number' => '#', + 'pages_revisions_numbered' => 'Revision #:id', + 'pages_revisions_numbered_changes' => 'Revision #:id Changes', 'pages_revisions_changelog' => 'Changelog', 'pages_revisions_changes' => 'Changes', 'pages_revisions_current' => 'Current Version', @@ -267,6 +275,7 @@ 'profile_not_created_pages' => ':userName has not created any pages', 'profile_not_created_chapters' => ':userName has not created any chapters', 'profile_not_created_books' => ':userName has not created any books', + 'profile_not_created_shelves' => ':userName has not created any shelves', // Comments 'comment' => 'Comment', diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index c38068afc00..e6c24f5a14f 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -12,34 +12,44 @@ 'settings_save_success' => 'Settings saved', // App Settings - 'app_settings' => 'App Settings', - 'app_name' => 'Application name', - 'app_name_desc' => 'This name is shown in the header and any emails.', - 'app_name_header' => 'Show Application name in header?', + 'app_customization' => 'Customization', + 'app_features_security' => 'Features & Security', + 'app_name' => 'Application Name', + 'app_name_desc' => 'This name is shown in the header and in any system-sent emails.', + 'app_name_header' => 'Show name in header', + 'app_public_access' => 'Public Access', + 'app_public_access_desc' => 'Enabling this option will allow visitors, that are not logged-in, to access content in your BookStack instance.', + 'app_public_access_desc_guest' => 'Access for public visitors can be controlled through the "Guest" user.', + 'app_public_access_toggle' => 'Allow public access', 'app_public_viewing' => 'Allow public viewing?', - 'app_secure_images' => 'Enable higher security image uploads?', + 'app_secure_images' => 'Higher Security Image Uploads', + 'app_secure_images_toggle' => 'Enable higher security image uploads', 'app_secure_images_desc' => 'For performance reasons, all images are public. This option adds a random, hard-to-guess string in front of image urls. Ensure directory indexes are not enabled to prevent easy access.', - 'app_editor' => 'Page editor', + 'app_editor' => 'Page Editor', 'app_editor_desc' => 'Select which editor will be used by all users to edit pages.', - 'app_custom_html' => 'Custom HTML head content', + 'app_custom_html' => 'Custom HTML Head Content', 'app_custom_html_desc' => 'Any content added here will be inserted into the bottom of the section of every page. This is handy for overriding styles or adding analytics code.', - 'app_logo' => 'Application logo', + 'app_logo' => 'Application Logo', 'app_logo_desc' => 'This image should be 43px in height.
Large images will be scaled down.', - 'app_primary_color' => 'Application primary color', + 'app_primary_color' => 'Application Primary Color', 'app_primary_color_desc' => 'This should be a hex value.
Leave empty to reset to the default color.', 'app_homepage' => 'Application Homepage', 'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.', 'app_homepage_select' => 'Select a page', - 'app_disable_comments' => 'Disable comments', - 'app_disable_comments_desc' => 'Disable comments across all pages in the application. Existing comments are not shown.', + 'app_disable_comments' => 'Disable Comments', + 'app_disable_comments_toggle' => 'Disable comments', + 'app_disable_comments_desc' => 'Disables comments across all pages in the application.
Existing comments are not shown.', // Registration Settings - 'reg_settings' => 'Registration Settings', - 'reg_allow' => 'Allow registration?', + 'reg_settings' => 'Registration', + 'reg_enable' => 'Enable Registration', + 'reg_enable_toggle' => 'Enable registration', + 'reg_enable_desc' => 'When registration is enabled user will be able to sign themselves up as an application user. Upon registration they are given a single, default user role.', 'reg_default_role' => 'Default user role after registration', - 'reg_confirm_email' => 'Require email confirmation?', - 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and the below value will be ignored.', - 'reg_confirm_restrict_domain' => 'Restrict registration to domain', + 'reg_email_confirmation' => 'Email Confirmation', + 'reg_email_confirmation_toggle' => 'Require email confirmation', + 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and this option will be ignored.', + 'reg_confirm_restrict_domain' => 'Domain Restriction', 'reg_confirm_restrict_domain_desc' => 'Enter a comma separated list of email domains you would like to restrict registration to. Users will be sent an email to confirm their address before being allowed to interact with the application.
Note that users will be able to change their email addresses after successful registration.', 'reg_confirm_restrict_domain_placeholder' => 'No restriction set', @@ -91,9 +101,16 @@ 'user_profile' => 'User Profile', 'users_add_new' => 'Add New User', 'users_search' => 'Search Users', + 'users_details' => 'User Details', + 'users_details_desc' => 'Set a display name and an email address for this user. The email address will be used for logging into the application.', + 'users_details_desc_no_email' => 'Set a display name for this user so others can recognise them.', 'users_role' => 'User Roles', + 'users_role_desc' => 'Select which roles this user will be assigned to. If a user is assigned to multiple roles the permissions from those roles will stack and they will receive all abilities of the assigned roles.', + 'users_password' => 'User Password', + 'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 5 characters long.', 'users_external_auth_id' => 'External Authentication ID', - 'users_password_warning' => 'Only fill the below if you would like to change your password:', + 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your LDAP system.', + 'users_password_warning' => 'Only fill the below if you would like to change your password.', 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', 'users_delete' => 'Delete User', 'users_delete_named' => 'Delete user :userName', @@ -104,8 +121,9 @@ 'users_edit_profile' => 'Edit Profile', 'users_edit_success' => 'User successfully updated', 'users_avatar' => 'User Avatar', - 'users_avatar_desc' => 'This image should be approx 256px square.', + 'users_avatar_desc' => 'Select an image to represent this user. This should be approx 256px square.', 'users_preferred_language' => 'Preferred Language', + 'users_preferred_language_desc' => 'This option will change the language used for the user-interface of the application. This will not affect any user-created content.', 'users_social_accounts' => 'Social Accounts', 'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.', 'users_social_connect' => 'Connect Account', diff --git a/resources/views/auth/forms/login/ldap.blade.php b/resources/views/auth/forms/login/ldap.blade.php index b52b5f13e91..ecdda652027 100644 --- a/resources/views/auth/forms/login/ldap.blade.php +++ b/resources/views/auth/forms/login/ldap.blade.php @@ -1,12 +1,12 @@
- @include('form/text', ['name' => 'username', 'tabindex' => 1]) + @include('form.text', ['name' => 'username', 'tabindex' => 1])
@if(session('request-email', false) === true)
- @include('form/text', ['name' => 'email', 'tabindex' => 1]) + @include('form.text', ['name' => 'email', 'tabindex' => 1]) {{ trans('auth.ldap_email_hint') }} @@ -15,5 +15,5 @@
- @include('form/password', ['name' => 'password', 'tabindex' => 2]) + @include('form.password', ['name' => 'password', 'tabindex' => 2])
\ No newline at end of file diff --git a/resources/views/auth/forms/login/standard.blade.php b/resources/views/auth/forms/login/standard.blade.php index 4ea1f35ba2b..a12fbd7531c 100644 --- a/resources/views/auth/forms/login/standard.blade.php +++ b/resources/views/auth/forms/login/standard.blade.php @@ -1,10 +1,10 @@
- @include('form/text', ['name' => 'email', 'tabindex' => 1]) + @include('form.text', ['name' => 'email', 'tabindex' => 1])
- @include('form/password', ['name' => 'password', 'tabindex' => 2]) - {{ trans('auth.forgot_password') }} + @include('form.password', ['name' => 'password', 'tabindex' => 1]) + {{ trans('auth.forgot_password') }}
\ No newline at end of file diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index f3847bb043a..eb7ca2da875 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,44 +1,48 @@ -@extends('public') - -@section('header-buttons') - @if(setting('registration-enabled', false)) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('login') {{ title_case(trans('auth.log_in')) }}

+
-
-
- {!! csrf_field() !!} +
 
- @include('auth/forms/login/' . $authMethod) +
+

{{ title_case(trans('auth.log_in')) }}

-
- - - -
+ + {!! csrf_field() !!} + +
+ @include('auth.forms.login.' . $authMethod) +
-
- +
+
+ @include('components.custom-checkbox', [ + 'name' => 'remember', + 'checked' => false, + 'value' => 'on', + 'label' => trans('auth.remember_me'), + ])
- +
+ +
+
+ + - @if(count($socialDrivers) > 0) -
- @foreach($socialDrivers as $driver => $name) - + @if(count($socialDrivers) > 0) +
+ @foreach($socialDrivers as $driver => $name) +
+
+ @endforeach + @endif
diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index 38f5cc07a9d..de4edff0a8e 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -1,37 +1,25 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} - @if(setting('registration-enabled')) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') +
+
+

{{ trans('auth.reset_password') }}

+

{{ trans('auth.reset_password_send_instructions') }}

-
-
-

@icon('permission') {{ trans('auth.reset_password') }}

- -
-

{{ trans('auth.reset_password_send_instructions') }}

+
+ {!! csrf_field() !!} - - {!! csrf_field() !!} +
+ + @include('form.text', ['name' => 'email']) +
-
- - @include('form/text', ['name' => 'email']) -
- -
- -
-
-
+
+ +
+
- @stop \ No newline at end of file diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index 0f66bd47360..fa6ad5b9a32 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -1,43 +1,34 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} - @if(setting('registration-enabled')) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('permission') {{ trans('auth.reset_password') }}

- -
-
- {!! csrf_field() !!} - - -
- - @include('form/text', ['name' => 'email']) -
- -
- - @include('form/password', ['name' => 'password']) -
- -
- - @include('form/password', ['name' => 'password_confirmation']) -
- -
- -
-
-
+
+
+

{{ trans('auth.reset_password') }}

+ +
+ {!! csrf_field() !!} + + +
+ + @include('form.text', ['name' => 'email']) +
+ +
+ + @include('form.password', ['name' => 'password']) +
+ +
+ + @include('form.password', ['name' => 'password_confirmation']) +
+ +
+ +
+
diff --git a/resources/views/auth/register-confirm.blade.php b/resources/views/auth/register-confirm.blade.php index 22d0f4acbd9..8fbf8abbbd7 100644 --- a/resources/views/auth/register-confirm.blade.php +++ b/resources/views/auth/register-confirm.blade.php @@ -1,19 +1,11 @@ -@extends('public') - -@section('header-buttons') - @if(!$signedIn) - @icon('login') {{ trans('auth.log_in') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('users') {{ trans('auth.register_thanks') }}

-
-

{{ trans('auth.register_confirm', ['appName' => setting('app-name')]) }}

-
+
+
+

{{ trans('auth.register_thanks') }}

+

{{ trans('auth.register_confirm', ['appName' => setting('app-name')]) }}

diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 900b394e3bf..d1e69e0a070 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -1,50 +1,54 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} -@stop +@extends('simple-layout') @section('content') +
-
-
-

@icon('new-user') {{ title_case(trans('auth.sign_up')) }}

-
-
- {!! csrf_field() !!} +
 
-
- - @include('form/text', ['name' => 'name']) -
+
+

{{ title_case(trans('auth.sign_up')) }}

-
- - @include('form/text', ['name' => 'email']) -
+ + {!! csrf_field() !!} -
- - @include('form/password', ['name' => 'password', 'placeholder' => trans('auth.password_hint')]) -
+
+ + @include('form.text', ['name' => 'name']) +
+ +
+ + @include('form.text', ['name' => 'email']) +
+ +
+ + @include('form.password', ['name' => 'password', 'placeholder' => trans('auth.password_hint')]) +
-
- +
+ - +
+ +
+
+ + + - @if(count($socialDrivers) > 0) -
- @foreach($socialDrivers as $driver => $name) - + @if(count($socialDrivers) > 0) +
+ @foreach($socialDrivers as $driver => $name) +
+
+ @endforeach + @endif
- - @stop diff --git a/resources/views/auth/user-unconfirmed.blade.php b/resources/views/auth/user-unconfirmed.blade.php index b02d45d22e9..54bf6eda331 100644 --- a/resources/views/auth/user-unconfirmed.blade.php +++ b/resources/views/auth/user-unconfirmed.blade.php @@ -1,34 +1,34 @@ -@extends('public') +@extends('simple-layout') @section('content') -
-

 

-
-

@icon('users') {{ trans('auth.email_not_confirmed') }}

-
-

{{ trans('auth.email_not_confirmed_text') }}
- {{ trans('auth.email_not_confirmed_click_link') }}
- {{ trans('auth.email_not_confirmed_resend') }} -

-
-
- {!! csrf_field() !!} -
- - @if(auth()->check()) - @include('form/text', ['name' => 'email', 'model' => auth()->user()]) - @else - @include('form/text', ['name' => 'email']) - @endif -
-
- -
-
-
-
+
+
+

{{ trans('auth.email_not_confirmed') }}

+ +

{{ trans('auth.email_not_confirmed_text') }}
+ {{ trans('auth.email_not_confirmed_click_link') }} +

+

+ {{ trans('auth.email_not_confirmed_resend') }} +

+
+ {!! csrf_field() !!} +
+ + @if(auth()->check()) + @include('form.text', ['name' => 'email', 'model' => auth()->user()]) + @else + @include('form.text', ['name' => 'email']) + @endif +
+
+ +
+
+ +
@stop diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index fdd248091d9..367a2cd8b9b 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -17,75 +17,29 @@ @yield('head') - - @include('partials/custom-styles') - + @include('partials.custom-styles') @include('partials.custom-head') - - - - @include('partials/notifications') - + @include('partials.notifications') + @include('common.header')
@yield('content')
-
+
@icon('chevron-up') {{ trans('common.back_to_top') }}
-@yield('bottom') - -@yield('scripts') + + @yield('bottom') + + @yield('scripts') + diff --git a/resources/views/books/create.blade.php b/resources/views/books/create.blade.php index 2d5e6c4558e..9079a3bf976 100644 --- a/resources/views/books/create.blade.php +++ b/resources/views/books/create.blade.php @@ -1,28 +1,27 @@ @extends('simple-layout') -@section('toolbar') - -@stop - @section('body') +
+
+ @include('partials.breadcrumbs', ['crumbs' => [ + '/books' => [ + 'text' => trans('entities.books'), + 'icon' => 'book' + ], + '/create-book' => [ + 'text' => trans('entities.books_create'), + 'icon' => 'add' + ] + ]]) +
-
-

 

-
-

@icon('add') {{ trans('entities.books_create') }}

-
+
+

{{ trans('entities.books_create') }}

- @include('books/form') + @include('books.form')
-
-


+ @include('components.image-manager', ['imageType' => 'cover']) @stop \ No newline at end of file diff --git a/resources/views/books/delete.blade.php b/resources/views/books/delete.blade.php index 0ac98e89567..2860e8bcdf1 100644 --- a/resources/views/books/delete.blade.php +++ b/resources/views/books/delete.blade.php @@ -1,28 +1,30 @@ @extends('simple-layout') -@section('toolbar') -
- @include('books._breadcrumbs', ['book' => $book]) -
-@stop - @section('body')
-

 

-
-

@icon('delete') {{ trans('entities.books_delete') }}

-
-

{{ trans('entities.books_delete_explain', ['bookName' => $book->name]) }}

-

{{ trans('entities.books_delete_confirmation') }}

-
- {!! csrf_field() !!} - - {{ trans('common.cancel') }} - -
-
+
+ @include('partials.breadcrumbs', ['crumbs' => [ + $book, + $book->getUrl('/delete') => [ + 'text' => trans('entities.books_delete'), + 'icon' => 'delete', + ] + ]]) +
+ +
+

{{ trans('entities.books_delete') }}

+

{{ trans('entities.books_delete_explain', ['bookName' => $book->name]) }}

+

{{ trans('entities.books_delete_confirmation') }}

+ +
+ {!! csrf_field() !!} + + {{ trans('common.cancel') }} + +
diff --git a/resources/views/books/edit.blade.php b/resources/views/books/edit.blade.php index cb1ffc46103..f048b543b63 100644 --- a/resources/views/books/edit.blade.php +++ b/resources/views/books/edit.blade.php @@ -1,24 +1,27 @@ @extends('simple-layout') -@section('toolbar') -
- @include('books._breadcrumbs', ['book' => $book]) -
-@stop - @section('body')
-

 

-
-

@icon('edit') {{ trans('entities.books_edit') }}

-
-
- - @include('books/form', ['model' => $book]) -
-
+ +
+ @include('partials.breadcrumbs', ['crumbs' => [ + $book, + $book->getUrl('/edit') => [ + 'text' => trans('entities.books_edit'), + 'icon' => 'edit', + ] + ]]) +
+ +
+

{{ trans('entities.books_edit') }}

+
+ + @include('books.form', ['model' => $book]) +
-@include('components.image-manager', ['imageType' => 'cover']) + + @include('components.image-manager', ['imageType' => 'cover']) @stop \ No newline at end of file diff --git a/resources/views/books/export.blade.php b/resources/views/books/export.blade.php index 18440a74da8..e1fabd800bd 100644 --- a/resources/views/books/export.blade.php +++ b/resources/views/books/export.blade.php @@ -31,51 +31,51 @@ @include('partials.custom-head') -
-
-
-
-

{{$book->name}}

+
-

{{ $book->description }}

+

{{$book->name}}

- @if(count($bookChildren) > 0) -
    - @foreach($bookChildren as $bookChild) -
  • {{ $bookChild->name }}
  • - @if($bookChild->isA('chapter') && count($bookChild->pages) > 0) - - @endif - @endforeach -
+

{{ $book->description }}

+ + @if(count($bookChildren) > 0) +
    + @foreach($bookChildren as $bookChild) +
  • {{ $bookChild->name }}
  • + @if($bookChild->isA('chapter') && count($bookChild->pages) > 0) + @endif + @endforeach +
+ @endif + + @foreach($bookChildren as $bookChild) +
+

{{ $bookChild->name }}

- @foreach($bookChildren as $bookChild) + @if($bookChild->isA('chapter')) +

{{ $bookChild->description }}

+ + @if(count($bookChild->pages) > 0) + @foreach($bookChild->pages as $page)
-

{{ $bookChild->name }}

- @if($bookChild->isA('chapter')) -

{{ $bookChild->description }}

- @if(count($bookChild->pages) > 0) - @foreach($bookChild->pages as $page) -
-
{{$bookChild->name}}
-

{{ $page->name }}

- {!! $page->html !!} - @endforeach - @endif - @else - {!! $bookChild->html !!} - @endif +
{{$bookChild->name}}
+

{{ $page->name }}

+ {!! $page->html !!} @endforeach + @endif + + @else + {!! $bookChild->html !!} + @endif + + @endforeach -
-
-
+ diff --git a/resources/views/books/form.blade.php b/resources/views/books/form.blade.php index bf94b5b076e..ebbc279fdb5 100644 --- a/resources/views/books/form.blade.php +++ b/resources/views/books/form.blade.php @@ -2,12 +2,12 @@ {{ csrf_field() }}
- @include('form/text', ['name' => 'name']) + @include('form.text', ['name' => 'name'])
- @include('form/textarea', ['name' => 'description']) + @include('form.textarea', ['name' => 'description'])
@@ -41,5 +41,5 @@
{{ trans('common.cancel') }} - +
\ No newline at end of file diff --git a/resources/views/books/grid-item.blade.php b/resources/views/books/grid-item.blade.php index 9bbf6910068..e1d37753a12 100644 --- a/resources/views/books/grid-item.blade.php +++ b/resources/views/books/grid-item.blade.php @@ -1,18 +1,19 @@ -
-